理性讨论本题三分在随机数据下的正确率
查看原帖
理性讨论本题三分在随机数据下的正确率
8457
chen_zheAya楼主2021/10/31 09:29

众所周知,一个单调增的函数加上一个单调减的函数,其结果并不一定是凸函数,也就是说三分是肯定有问题的。但是对于一个非凸函数进行三分,其结果也未必错。

本题根据各位的得分情况,可以得知:数据强度较弱,应该是随机生成的数据;若是对三分进行特判,当 r-l<50 跑暴力可以通过。那么不得不提出一个问题:在随机数据下,三分的实践效果究竟如何呢?欢迎各位进行探讨,我也不会。

参考代码(洛谷 80pts,CCF 95pts):

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <cstring>
#include <set>

using namespace std;

int n,m1,m2,g1[500050],g2[500050],t1[500050],t2[500050],st1[500050],st2[500050],ss1[500050],ss2[500050];

struct node
{
	int s,t;
	bool operator <(const node &rhs) const
	{
		return s!=rhs.s?s<rhs.s:t<rhs.t;
	}
}a[200050],b[200050],a1[200050],b1[200050];

inline int solve(int x)
{
	int now=0,lret=0,rret=0;
	priority_queue <int> q;
	while (!q.empty())
		q.pop();
	for (int j=1;j<=m1;j++)
	{
		while (!q.empty() && (-q.top()<a1[j].s))
		{
			now--;
			q.pop();
		}
		if (now+1<=x)
		{
			now++;
			lret++;
			q.push(-a1[j].t);
		}
	}
	//cout << i << " " << lret << endl;
	now=0;
	while (!q.empty())
		q.pop();
	for (int j=1;j<=m2;j++)
	{
		while (!q.empty() && (-q.top()<b1[j].s))
		{
			now--;
			q.pop();
		}
		if (now+1<=n-x)
		{
			now++;
			rret++;
			q.push(-b1[j].t);
		}
	}
	return lret+rret;
}

int main()
{
	scanf("%d%d%d",&n,&m1,&m2);
	for (int i=1;i<=m1;i++)
	{
		scanf("%d%d",&a[i].s,&a[i].t);
		t1[++t1[0]]=a[i].s;
		t1[++t1[0]]=a[i].t;
	}
	for (int i=1;i<=m2;i++)
	{
		scanf("%d%d",&b[i].s,&b[i].t);
		t2[++t2[0]]=b[i].s;
		t2[++t2[0]]=b[i].t;
	}
	sort(t1+1,t1+t1[0]+1);
	int ct1=unique(t1+1,t1+t1[0]+1)-t1-1;
	for (int i=1;i<=ct1;i++)
	{
		a1[i].s=lower_bound(t1+1,t1+ct1+1,a[i].s)-t1;
		a1[i].t=lower_bound(t1+1,t1+ct1+1,a[i].t)-t1;
	}
	sort(t2+1,t2+t2[0]+1);
	int ct2=unique(t2+1,t2+t2[0]+1)-t2-1;
	for (int i=1;i<=ct2;i++)
	{
		b1[i].s=lower_bound(t2+1,t2+ct2+1,b[i].s)-t2;
		b1[i].t=lower_bound(t2+1,t2+ct2+1,b[i].t)-t2;
	}
		
	sort(a1+1,a1+m1+1);
	sort(b1+1,b1+m2+1);

	for (int j=1;j<=m1;j++)
	{
		g1[a1[j].s]++;
		g1[a1[j].t]--;
	}
	for (int j=1;j<=m2;j++)
	{
		g2[b1[j].s]++;
		g2[b1[j].t]--;
	}
	int ans=0;
	if (n<=5001)
	{
		for (int i=0;i<=n;i++)
		{
			int now=0,lret=0,rret=0;
			priority_queue <int> q;
			while (!q.empty())
				q.pop();
			for (int j=1;j<=m1;j++)
			{
				while (!q.empty() && (-q.top()<a1[j].s))
				{
					now--;
					q.pop();
				}
				if (now+1<=i)
				{
					now++;
					lret++;
					q.push(-a1[j].t);
				}
			}
			//cout << i << " " << lret << endl;
			now=0;
			while (!q.empty())
				q.pop();
			for (int j=1;j<=m2;j++)
			{
				while (!q.empty() && (-q.top()<b1[j].s))
				{
					now--;
					q.pop();
				}
				if (now+1<=n-i)
				{
					now++;
					rret++;
					q.push(-b1[j].t);
				}
			}
			ans=max(ans,lret+rret);
		}
		cout << ans << endl;
	}
	else
	{
		int l=0,r=n;
		for (int i=1;i<=40;i++)
		{
			int x1=l+(r-l)/3;
			int x2=r-(r-l)/3;
			if (solve(x1)>solve(x2))
				r=x2;
			else
				l=x1;
		}
		cout << max(max(solve(l),solve(r)),max(max(solve(l+1),solve(r-1)),max(solve(l-1),solve(r+1)))) << endl;
	}
	fclose(stdin);
	fclose(stdout);
	return 0;
}

根据学术版管理规定:发布无意义内容(例如单纯膜人,前排等),第一次给予删除,第二次禁言。

2021/10/31 09:29
加载中...