2019.10.26【NOIP提高组】模拟 A 组

T1:比赛的时候我以为想到了正解,但是调了很长时间之后我发现了错误。正解和我的方法还是有很大差别的。

正解如下:首先贪心算出ans。然后我们从前往后枚举b的每一位放什么。

对于第i位,我们把剩下没有用过的b分成两部分——小于等于a[i]的和大于a[i]的。那么我们就可以二分两次来求b[i]了。易证b的合法性在两部分之中是有单调性的。至于判定,我们可以在二分除了mid之后再O(n)贪心做一遍剩下的数,求出第i为放mid的答案。

T2:这题我比赛时想到了正解,但是没时间打了。

二分答案,然后我们发现剩下的就是一个扫描线问题。

具体操作不好讲,还是看代码吧:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
#define MAXN 50010
#define pi M_PI
using namespace std;

struct point
{
	double x;
	double y;
	ll rank;
	double v;
};
point a[MAXN];
struct sor
{
	double v;
	ll num;
};
sor b[MAXN];
ll f[MAXN],n;
double ans,k,w;
const double L=0.000000001;
int game1(const sor &a,const sor &b)
{
	if(a.v<b.v)return 1;
	else return 0;
}
int game2(const point &a,const point &b)
{
	if(a.v*w-b.v*w<0)return 1;
	if(a.v*w-b.v*w>0)return 0;
	if(a.y>b.y)return 1;
	else return 0;
}
ll sum(ll x)
{
	ll i=x,s=0;
	while(i>=1){s+=f[i];i=i-(i&(-i));}
	return s;
}
ll change(ll x)
{
	ll i=x;
	while(i<=n){f[i]++;i=i+(i&(-i));}
}
double find(ll num)
{
	ll i,j,s;
	double l,r;
	l=0;r=pi;
	while(l<=r)
	{
		k=(l+r)/2;w=tan(k);
		for(i=1;i<=n;i++)a[i].v=a[i].y-w*a[i].x;
		sort(a+1,a+n+1,game2);
		memset(f,0,sizeof(f));
		s=0;
		for(i=1;i<=n;i++)
		{
			s=s+sum(n)-sum(a[i].rank-1);
			change(a[i].rank);
		}
		if(s<=num-1)ans=k,l=k+L;
		else r=k-L;
	}
	return ans;
}
int main()
{
//freopen("line.in","r",stdin);
//freopen("line.out","w",stdout);
ll i,j,w=0;
scanf("%lld",&n);
for(i=1;i<=n;i++)scanf("%lf %lf",&a[i].x,&a[i].y);
for(i=1;i<=n;i++)b[i].v=a[i].y,b[i].num=i;
sort(b+1,b+n+1,game1);
for(i=1;i<=n;i++)
{
	if(b[i].v!=b[i-1].v||i==1)w++;
	a[b[i].num].rank=w;
}
if((n*(n-1)/2)%2==1)printf("%.10lf",find(n*(n-1)/2/2+1));
else printf("%.10lf",(find(n*(n-1)/2/2)+find(n*(n-1)/2/2+1))/2);
}

T3:首先假设我们已经建完图了,那么设g[i]表示有多少个j满足j>i且i、j有连边,那么ans=\prod (n-g[i])。这是因为在i后面与i有连边的所有点必定构成一个完全图,所以这个完全图中的点两两的颜色肯定是不同的,而i有与它们都有连边,所以i就只剩下了(n-g[i])中选择。所有i的方案乘起来就是答案了。

那么现在的问题就是求g,这里有一个简单的方法:

从前往后扫,对于每个点维护一棵线段树,然后把i的线段树合并到i后面与i最近的有连边的点,这样我们就可以在O(nlogn)的复杂度内构完图。实现时可以线段树合并,也可以set+启发式合并(set维护每一个点连向的点)。

发布了149 篇原创文章 · 获赞 24 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/chiyankuan/article/details/102761156