Description
Cirno闲着无事的时候喜欢冰冻青蛙。
Cirno每次从雾之湖中固定的n个结点中选出一些点构成一个简单多边形,Cirno运用自己的能力能将此多边形内所有青蛙冰冻。
雾之湖生活着m只青蛙,青蛙有大有小,所以每只青蛙的价值为一个不大于10000的正整数。
Cirno很想知道每次冻住的青蛙的价值总和。因为智商有限,Cirno将这个问题交给完美算术教室里的你。
因为爱护动物,所以每次冻结的青蛙会被放生。也就是说一只青蛙可以被多次统计。
-10000<=x,y<=10000; 0
Solution
计算几何式懵逼
我们知道可以先选择一个原点,然后通过类似叉积的做法求出这个多边形的有向面积
这里的面积定义成内部的点的个数
于是我们只需要求出每个三角形内部的点的权值和,两次排序之后树状数组维护即可。
Code
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
typedef double db;
typedef long long ll;
const int N=1e3+5;
int n,m,ans,Q,a[N],ord[N],S,Ans[N<<1][N<<1],tr[N<<1];
db eps=1e-7;
void ins(int x,int y) {for(;x<=n+m;x+=x&-x) tr[x]+=y;}
int query(int x) {int res=0;for(;x;x-=x&-x) res+=tr[x];return res;}
int find(int l,int r) {
if (l>r) swap(l,r);
return query(r)-query(l-1);
}
struct P{
int x,y,v,id,w;db a;
P(int _x=0,int _y=0) {x=_x;y=_y;v=id=w=a=0;}
friend P operator + (P x,P y) {return P(x.x+y.x,x.y+y.y);}
friend P operator - (P x,P y) {return P(x.x-y.x,x.y-y.y);}
}p[N<<1],O,q[N<<1];
int cross(P x,P y) {return x.x*y.y-y.x*x.y;}
int sig(int x) {
if (x>0) return 1;
if (x==0) return 0;
if (x<0) return -1;
}
bool cmp(P x,P y) {return x.a<y.a;}
db theta(P x,P y) {
db a=x.x*y.x+x.y*y.y;
a/=sqrt(x.x*x.x+x.y*x.y)*sqrt(y.x*y.x+y.y*y.y);
return acos(a);
}
int main() {
scanf("%d%d",&n,&m);
fo(i,1,n) scanf("%d%d",&p[i].x,&p[i].y),p[i].id=i;
fo(i,1,m) scanf("%d%d%d",&p[i+n].x,&p[i+n].y,&p[i+n].v);
O=P(-20000,-20000);
fo(i,1,n+m) p[i].a=atan2(p[i].y-O.y,p[i].x-O.x);
sort(p+1,p+n+m+1,cmp);
fo(i,1,n+m) {
p[i].w=i;
if (p[i].id) ord[p[i].id]=i;
}
fo(i,1,n+m)
if (!p[i].v) {
int tot=0;
fo(j,i+1,n+m) {
q[++tot]=p[j];
q[tot].a=theta(p[j]-O,p[i]-O)+theta(O-p[j],p[i]-p[j]);
}
sort(q+1,q+tot+1,cmp);
fo(j,1,tot)
if (q[j].v) ins(q[j].w,q[j].v);
else Ans[i][q[j].w]=Ans[q[j].w][i]=find(q[j].w,p[i].w);
fo(j,1,tot) if (q[j].v) ins(q[j].w,-q[j].v);
}
for(scanf("%d",&Q);Q;Q--) {
scanf("%d",&S);
int ans=0;
fo(i,1,S) {
scanf("%d",&a[i]);a[i]=ord[a[i]];
if (i!=1) ans+=sig(cross(p[a[i]]-O,p[a[i-1]]-O))*Ans[a[i]][a[i-1]];
}
ans+=sig(cross(p[a[1]]-O,p[a[S]]-O))*Ans[a[1]][a[S]];
if (ans<0) ans=-ans;
printf("%d\n",ans);
}
return 0;
}