codeforces1195F

题目描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

题目大意

定义两个凸多边形的“合并”:将凸多边形内的每个点相加(向量加)组成一个新凸多边形
若干次询问,求[L,R]内凸多边形相加后得到的凸多边形的顶点数

前言

因为C题读错题导致E题没调出来,rank2000+
F题比赛时没看,后来发现不难

正解

一个并不显然的结论:
两个凸多边形相加得到的顶点数为这两个多边形同逆时针方向上不同的方向种类
感性证明一下
凸多边形相加等于将一个凸多边形按另一个的边界移动
如果另一个的一条向量的方向在第一个中没有出现,那么移动后就一定会多出一条


然后就很偷税愉悦地离散化+莫队乱搞

code

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define PI 3.14159265358979323846
using namespace std;

struct type{
	double s;
	int id;
} a[300001];
int b[300001];
int ls[100001];
double x[300001];
double y[300001];
struct Type{
	int l,r,s,id;
} q[100001];
int ans[100001];
int c[300001];
int N,Q,n,i,j,k,tot,Ans,S,l,r;

bool cmp(type a,type b)
{
	return a.s<b.s;
}

bool Cmp(Type a,Type b)
{
	return a.s<b.s || a.s==b.s && a.r<b.r;
}

int gcd(int n,int m)
{
	int r=n%m;
	
	while (!r)
	{
		n=m;
		m=r;
		r=n%m;
	}
	
	return m;
}

double xl(int i,int j)
{
	if (x[i]==x[j])
	return (y[i]<y[j])?PI/2:PI*1.5;
	else
	if (y[i]==y[j])
	return (x[i]<x[j])?0:PI;
	else
	if (y[i]<y[j])
	{
		if (x[i]<x[j])
		return atan((y[j]-y[i])/(x[j]-x[i]));
		else
		return atan((y[j]-y[i])/(x[j]-x[i]))+PI;
	}
	else
	{
		if (x[j]<x[i])
		return atan((y[j]-y[i])/(x[j]-x[i]))+PI;
		else
		return atan((y[j]-y[i])/(x[j]-x[i]))+PI+PI;
	}
}

int main()
{
//	freopen("f.in","r",stdin);
	
	scanf("%d",&N);
	fo(l,1,N)
	{
		ls[l]=tot+1;
		
		scanf("%d",&n);
		fo(i,1,n)
		scanf("%lf%lf",&x[i],&y[i]);
		
		fo(i,1,n-1)
		{
			++tot;
			a[tot].s=xl(i,i+1);
			a[tot].id=tot;
		}
		++tot;
		a[tot].s=xl(n,1);
		a[tot].id=tot;
	}
	ls[N+1]=tot+1;
	S=floor(sqrt(tot));
	
	sort(a+1,a+tot+1,cmp);
	
	j=0;
	fo(i,1,tot)
	{
		if (i==1 || a[i].s-a[i-1].s>0.00000000001)
		++j;
		b[a[i].id]=j;
	}
	
	scanf("%d",&Q);
	fo(i,1,Q)
	{
		scanf("%d%d",&q[i].l,&q[i].r);
		q[i].l=ls[q[i].l];
		q[i].r=ls[q[i].r+1]-1;
		q[i].id=i;
		q[i].s=q[i].l/S;
	}
	
	sort(q+1,q+Q+1,Cmp);
	
	l=0;
	r=0;
	Ans=0;
	fo(i,1,Q)
	{
		while (q[i].l<l)
		{
			--l;
			++c[b[l]];
			if (c[b[l]]==1)
			++Ans;
		}
		while (r<q[i].r)
		{
			++r;
			++c[b[r]];
			if (c[b[r]]==1)
			++Ans;
		}
		
		while (l<q[i].l)
		{
			--c[b[l]];
			if (!c[b[l]])
			--Ans;
			++l;
		}
		while (q[i].r<r)
		{
			--c[b[r]];
			if (!c[b[r]])
			--Ans;
			--r;
		}
		
		ans[q[i].id]=Ans;
	}
	
	fo(i,1,Q)
	printf("%d\n",ans[i]);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章