题目描述
题目大意
定义两个凸多边形的“合并”:将凸多边形内的每个点相加(向量加)组成一个新凸多边形
若干次询问,求[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]);
}