「BZOJ2391」Cirno的忧郁
设p[0] = (-10001,-10001)
把所有点按p[0]极角排序,
s[i][j]表示三角形p[0]p[i]p[j]内的总价值,若i到j极角增大则s为正,否则s为负。
那么答案就是按顺序多边形每条边两个端点的s值之和的绝对值。
如何求s
枚举每个点x,建一颗平衡树,把极角排序在它后面的点一个个加入平衡树,树中的权值为按x极角排序的值。那么加入一个点y时,权值小于y的权值的所有点的和即为s[x][y]。
//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<queue>
#include<cmath>
#define eps 1e-15
#define For(i,a,b) for(int i=(a);i<=(b);i++)
#define Rep(i,a,b) for(int i=(a);i>=(b);i--)
const int N=2007;
typedef long long LL;
typedef double db;
using namespace std;
int n,m,q,qs[N],rak[N];
template<typename T>void read(T &x) {
char ch=getchar(); x=0; T f=1;
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') f=-1,ch=getchar();
for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
}
struct pt {
LL x,y,w; int id; db slop;
pt(){}
pt(LL x,LL y):x(x),y(y){}
}p[N];
pt operator - (const pt&A,const pt&B) { return pt(A.x-B.x,A.y-B.y); }
LL cross(pt A,pt B) { return A.x*B.y-A.y*B.x; }
LL dot(pt A,pt B) { return A.x*B.x+A.y*B.y; }
LL length(pt A) { return dot(A,A); }
int dcmp(db x) { return fabs(x)<=eps?0:(x>0?1:-1); }
bool operator <(const pt&A,const pt&B) {
return dcmp(A.slop-B.slop)>0||(dcmp(A.slop-B.slop)==0&&length(A-p[0])<length(B-p[0]));
}
db v[N];
LL w[N],s[N][N],sum[N],rs;
int rt,tot,l[N],r[N],hr[N];
#define lc l[x]
#define rc r[x]
void update(int x) { sum[x]=sum[lc]+sum[rc]+w[x]; }
void left(int &x) {
int y=r[x];
r[x]=l[y];
l[y]=x;
update(x);
x=y;
update(x);
}
void right(int &x) {
int y=l[x];
l[x]=r[y];
r[y]=x;
update(x);
x=y;
update(x);
}
void insert(int &x,db y,LL ww) {
if(!x) {
x=++tot;
hr[x]=rand();
lc=rc=0;
v[x]=y;
sum[x]=w[x]=ww;
rs+=ww;
return ;
}
if(v[x]<y) {
rs+=sum[lc]+w[x];
insert(rc,y,ww);
if(hr[rc]<hr[x]) left(x);
}
else {
insert(lc,y,ww);
if(hr[lc]<hr[x]) right(x);
}
update(x);
}
LL solve(int k) {
LL res=0;
qs[k+1]=qs[1];
For(i,1,k)
res+=s[rak[qs[i]]][rak[qs[i+1]]];
return abs(res);
}
#define DEBUG
int main() {
#ifdef DEBUG
freopen("2391.in","r",stdin);
freopen("2391.out","w",stdout);
#endif
srand(998244353);
read(n); read(m);
For(i,1,n) read(p[i].x),read(p[i].y),p[i].id=i,p[i].w=0;
For(i,1,m) read(p[n+i].x),read(p[n+i].y),read(p[n+i].w);
p[0]=pt(-12345,-15432);
For(i,1,n+m) p[i].slop=atan2(p[i].y-p[0].y,p[i].x-p[0].x);
sort(p+1,p+n+m+1);
For(i,1,n+m) if(p[i].id) rak[p[i].id]=i;
For(i,1,n+m) {
rt=0; tot=0;
For(j,i,n+m) {
if(j==1008) {
int debug=1;
}
rs=0;
insert(rt,atan2(p[j].y-p[i].y,p[j].x-p[i].x),p[j].w);
s[i][j]=rs; s[j][i]=-rs;
}
}
read(q);
while(q--) {
int k;
read(k);
For(i,1,k) read(qs[i]);
printf("%lld\n",solve(k));
}
return 0;
}