題目描述
題目大意
定義兩個凸多邊形的“合併”:將凸多邊形內的每個點相加(向量加)組成一個新凸多邊形
若干次詢問,求[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]);
}