2391: Cirno的忧郁

Description
 
Cirno闲着无事的时候喜欢冰冻青蛙。
Cirno每次从雾之湖中固定的n个结点中选出一些点构成一个简单多边形,Cirno运用自己的能力能将此多边形内所有青蛙冰冻。
雾之湖生活着m只青蛙,青蛙有大有小,所以每只青蛙的价值为一个不大于10000的正整数。
Cirno很想知道每次冻住的青蛙的价值总和。因为智商有限,Cirno将这个问题交给完美算术教室里的你。
因为爱护动物,所以每次冻结的青蛙会被放生。也就是说一只青蛙可以被多次统计。
 
Input
 
第一行2个正整数 n,m。
以下n行,每行2个整数xi,yi,表示第i个结点的坐标。
再以下m行,每行3个整数xj,yj,vj,表示第j个青蛙的坐标和价值。
第n+m+1行一个整数q,表示有q组询问。
每组询问有2行,第一行一个整数s(3<=s<=n),表示简单多边形的结点数。第二行s个正整数,顺时针或逆时针给出多边形的结点的编号(1--n)
 
Output
 
q行。
对于每个询问,每行输出一个整数表示冻结的青蛙的价值之和
 
Sample Input
4 3
2 2
3 5
7 4
5 1
3 4 2
4 3 7
6 3 90
2
3
1 2 3
4
1 4 3 2

Sample Output
9
99

HINT

数据范围】

对于30%的数据,n,m<=100; q<=100

对于60%的数据,n,m<=100; q<=10000

对于100%的数据,n,m<=1000; q<=10000

                -10000<=x,y<=10000; 0<v<=10000

看见他三次了,还是写了吧

我们预处理出s[i,j]表示线段[i,j)下面的点权和

然后就可以像求多边形面积一样求权值和了

预处理这个很简单,枚举一个端点,然后极角排序,按顺序加点,用树状数组维护和加到点j的时候s[i,j]=sum(xi,xj-1),因为两个端点不能同时取要不然就多了,感觉有点像cdq分治

  1 const
  2     maxn=1010;
  3 type
  4     point=record
  5         x,y,id,v:longint;
  6     end;
  7     aa=array[0..maxn*2]of longint;
  8 var
  9     a,b:array[0..maxn*2]of point;
 10     s:array[0..maxn,0..maxn]of longint;
 11     x,c:aa;
 12     n,m,q:longint;
 13 
 14 procedure swap(var x,y:longint);
 15 var
 16     t:longint;
 17 begin
 18     t:=x;x:=y;y:=t;
 19 end;
 20 
 21 procedure sort(l,r:longint;var a:aa);
 22 var
 23     i,j,y:longint;
 24 begin
 25     i:=l;j:=r;y:=a[(l+r)>>1];
 26     repeat
 27         while a[i]<y do inc(i);
 28         while a[j]>y do dec(j);
 29         if i<=j then
 30         begin
 31             swap(a[i],a[j]);
 32             inc(i);dec(j);
 33         end;
 34     until i>j;
 35     if i<r then sort(i,r,a);
 36     if j>l then sort(l,j,a);
 37 end;
 38 
 39 operator -(a,b:point)c:point;
 40 begin
 41     c.x:=a.x-b.x;
 42     c.y:=a.y-b.y;
 43 end;
 44 
 45 operator *(a,b:point)c:longint;
 46 begin
 47     exit(a.x*b.y-a.y*b.x);
 48 end;
 49 
 50 procedure swap(var x,y:point);
 51 var
 52     t:point;
 53 begin
 54     t:=x;x:=y;y:=t;
 55 end;
 56 
 57 procedure sort(l,r:longint);
 58 var
 59     i,j:longint;
 60     y:point;
 61 begin
 62     i:=l;j:=r;y:=a[(l+r)>>1];
 63     repeat
 64         while (y-a[0])*(a[i]-a[0])<0 do inc(i);
 65         while (y-a[0])*(a[j]-a[0])>0 do dec(j);
 66         if i<=j then
 67         begin
 68             swap(a[i],a[j]);
 69             inc(i);dec(j);
 70         end;
 71     until i>j;
 72     if i<r then sort(i,r);
 73     if j>l then sort(l,j);
 74 end;
 75 
 76 function find(k:longint):longint;
 77 var
 78     l,r,mid:longint;
 79 begin
 80     l:=1;r:=n+m;
 81     while l<>r do
 82         begin
 83             mid:=(l+r)>>1;
 84             if x[mid]<k then l:=mid+1
 85             else r:=mid;
 86         end;
 87     exit(l);
 88 end;
 89 
 90 procedure add(x,y:longint);
 91 begin
 92     while x<=n+m do
 93         begin
 94             inc(c[x],y);
 95             x:=x+(x and (-x));
 96         end;
 97 end;
 98 
 99 function sum(x:longint):longint;
100 begin
101     sum:=0;
102     while x>0 do
103         begin
104             inc(sum,c[x]);
105             x:=x-(x and (-x));
106         end;
107 end;
108 
109 procedure main;
110 var
111     i,j,cnt,ans:longint;
112 begin
113     read(n,m);
114     for i:=1 to n do
115         begin
116             read(a[i].x,a[i].y);
117             b[i]:=a[i];
118             a[i].id:=i;
119         end;
120     for i:=n+1 to n+m do
121         read(a[i].x,a[i].y,a[i].v);
122     for i:=1 to n+m do
123         x[i]:=a[i].x;
124     sort(1,n+m,x);
125     for i:=1 to n do
126         begin
127             for j:=1 to n+m do
128                 c[j]:=0;
129             a[0]:=b[i];
130             cnt:=0;
131             for j:=1 to n+m do
132                 if (a[j].x>=a[0].x) and ((a[j].x<>a[0].x) or (a[j].y<>a[0].y)) then
133                 begin
134                     inc(cnt);
135                     swap(a[j],a[cnt]);
136                 end;
137             sort(1,cnt);
138             for j:=1 to cnt do
139                 begin
140                     if a[j].id>0 then s[i,a[j].id]:=sum(find(a[j].x)-1)
141                     else add(find(a[j].x),a[j].v);
142                 end;
143         end;
144     for i:=1 to n do
145         for j:=1 to n do
146             if s[i,j]=0 then s[i,j]:=-s[j,i];
147     read(q);
148     for i:=1 to q do
149         begin
150             read(cnt);
151             for j:=1 to cnt do
152                 read(x[j]);
153             ans:=0;
154             for j:=1 to cnt do
155                 inc(ans,s[x[j],x[j mod cnt+1]]);
156             writeln(abs(ans));
157         end;
158 end;
159 
160 begin
161     main;
162 end.
View Code
原文地址:https://www.cnblogs.com/Randolph87/p/3801198.html