bzoj4009

这是一道神题,首先我们不难先到整体二分吧

下面的问题就是,求出对于每个水果,有多少盘子是他的子路径

直接考虑不是很容易,我们换个思路,考虑对于每个盘子,哪些水果能包含它

我们假设盘子a,b,dep[a]<dep[b]

如果b在a的子树内,不难发现,水果路径必须是一个点在b的子树内(包括b),一个在c的子树外(不包括c,c是ab路径上a下一个点)

否则 ,水果路径必须两个点分别在a,b子树内

子树问题不难想到dfs序,设子树x区间为l[x],r[x],盘子路径x,y(l[x]<l[y])满足条件为

则要满足x∈[1,l[c]-1],y∈[l[b],r[b]或x∈[l[b],r[b]], y∈[l[c]+1,n] 当b在a的子树内

否则x∈[l[a],r[a]],y∈[l[b],r[b],把(x,y)看做一个点

也就是现在询问每个点被多少矩形覆盖(注意第一种情形两个矩形是不相交的,所以覆盖的矩形数目就是盘子数目

矩形覆盖的经典做法是把矩形(x0,y0),(x1,y1)看成4个带权值的点

(x0,y0) 1, (x0,y1+1) -1, (x1+1,y0) -1 (x1+1,y1+1) 1,

这样每个询问点最下方(包括边界)的点权值和就是覆盖询问点的矩形数目(画图可知)

而这个问题我们对一维排序,一维树状数组即可快速解决

  1 type node=record
  2        po,next:longint;
  3      end;
  4      point=record
  5        x,y,id,z:longint;
  6      end;
  7 
  8 var e:array[0..80010] of node;
  9     dep,ans,st,a,b,c,p,d:array[0..50010] of longint;
 10     anc:array[0..40010,0..18] of longint;
 11     q,w,tw:array[0..400010] of point;
 12     can,v:array[0..80010] of boolean;
 13     j,tot,t,x,y,z,i,len,n,m,k,xx:longint;
 14 
 15 function lowbit(x:longint):longint;
 16   begin
 17     exit(x and (-x));
 18   end;
 19 
 20 procedure swap(var a,b:longint);
 21   var c:longint;
 22   begin
 23     c:=a;
 24     a:=b;
 25     b:=c;
 26   end;
 27 
 28 procedure add(x,y:longint);
 29   begin
 30     inc(len);
 31     e[len].po:=y;
 32     e[len].next:=p[x];
 33     p[x]:=len;
 34   end;
 35 
 36 procedure dfs(x:longint);
 37   var i,y:longint;
 38   begin
 39     inc(t);
 40     a[x]:=t;
 41     i:=p[x];
 42     while i<>0 do
 43     begin
 44       y:=e[i].po;
 45       if a[y]=0 then
 46       begin
 47         anc[y,0]:=x;
 48         dep[y]:=dep[x]+1;
 49         dfs(y);
 50       end;
 51       i:=e[i].next;
 52     end;
 53     b[x]:=t;
 54   end;
 55 
 56 function jump(x,d:longint):longint;
 57   var i:longint;
 58   begin
 59     for i:=16 downto 0 do
 60       if dep[x]-1 shl i>=d then x:=anc[x,i];
 61     exit(x);
 62   end;
 63 
 64 function cmp(a,b:point):boolean;
 65   begin
 66     exit((a.x<b.x) or (a.x=b.x) and (a.y<b.y));
 67   end;
 68 
 69 procedure sortc(l,r:longint);
 70   var i,j,x:longint;
 71   begin
 72     i:=l;
 73     j:=r;
 74     x:=c[(l+r) shr 1];
 75     repeat
 76       while c[i]<x do inc(i);
 77       while x<c[j] do dec(j);
 78       if not(i>j) then
 79       begin
 80         swap(c[i],c[j]);
 81         inc(i);
 82         dec(j);
 83       end;
 84     until i>j;
 85     if l<j then sortc(l,j);
 86     if i<r then sortc(i,r);
 87   end;
 88 
 89 procedure sortw(l,r:longint);
 90   var i,j:longint;
 91       x,y:point;
 92   begin
 93     i:=l;
 94     j:=r;
 95     x:=w[(l+r) shr 1];
 96     repeat
 97       while cmp(w[i],x) do inc(i);
 98       while cmp(x,w[j]) do dec(j);
 99       if not(i>j) then
100       begin
101         y:=w[i]; w[i]:=w[j]; w[j]:=y;
102         inc(i);
103         dec(j);
104       end;
105     until i>j;
106     if l<j then sortw(l,j);
107     if i<r then sortw(i,r);
108   end;
109 
110 procedure sortq(l,r:longint);
111   var i,j:longint;
112       x,y:point;
113   begin
114     i:=l;
115     j:=r;
116     x:=q[(l+r) shr 1];
117     repeat
118       while cmp(q[i],x) do inc(i);
119       while cmp(x,q[j]) do dec(j);
120       if not(i>j) then
121       begin
122         y:=q[i]; q[i]:=q[j]; q[j]:=y;
123         inc(i);
124         dec(j);
125       end;
126     until i>j;
127     if l<j then sortq(l,j);
128     if i<r then sortq(i,r);
129   end;
130 
131 procedure open(x0,x1,y0,y1,z:longint);
132   begin
133     inc(x1); inc(y1);
134     inc(t); w[t].x:=x0; w[t].y:=y0; w[t].id:=1; w[t].z:=z;
135     inc(t); w[t].x:=x0; w[t].y:=y1; w[t].id:=-1; w[t].z:=z;
136     inc(t); w[t].x:=x1; w[t].y:=y0; w[t].id:=-1; w[t].z:=z;
137     inc(t); w[t].x:=x1; w[t].y:=y1; w[t].id:=1; w[t].z:=z;
138   end;
139 
140 procedure work(x,w:longint);
141   begin
142     while x<=n+1 do
143     begin
144       if not v[x] then
145       begin
146         v[x]:=true;
147         inc(tot);
148         st[tot]:=x;
149       end;
150       d[x]:=d[x]+w;
151       x:=x+lowbit(x);
152     end;
153   end;
154 
155 function ask(x:longint):longint;
156   begin
157     ask:=0;
158     while x>0 do
159     begin
160       ask:=ask+d[x];
161       x:=x-lowbit(x);
162     end;
163   end;
164 
165 procedure cdq(opx,opy,qx,qy,l,r:longint);
166   var m,t,i,j,s,f1,f2,z,q1,q2:longint;
167   begin
168     if (l>r) or (qx>qy) then exit;
169     if l=r then
170     begin
171       for i:=qx to qy do
172         ans[q[i].id]:=c[l];
173       exit;
174     end;
175     m:=(l+r) shr 1;  //二分答案
176     t:=0;
177     for i:=opx to opy do
178       if w[i].z<=c[m] then
179       begin
180         inc(t);
181         tw[t]:=w[i];
182       end;
183 
184     z:=0;
185     j:=1;
186     for i:=qx to qy do
187     begin
188       can[i]:=false;
189       while (j<=t) and (tw[j].x<=q[i].x) do  //扫描询问
190       begin
191         work(tw[j].y,tw[j].id);
192         inc(j);
193       end;
194       s:=ask(q[i].y);
195       if s>=q[i].z then
196       begin
197         ans[q[i].id]:=c[m];
198         inc(z);
199         can[i]:=true;
200       end
201       else q[i].z:=q[i].z-s;
202     end;
203     f1:=opx-1; f2:=opx+t-1;  //划分操作区间
204     for i:=opx to opy do
205       if w[i].z<=c[m] then
206       begin
207         inc(f1);
208         tw[f1]:=w[i];
209       end
210       else begin
211         inc(f2);
212         tw[f2]:=w[i];
213       end;
214     for i:=opx to opy do
215       w[i]:=tw[i];
216     q1:=qx-1; q2:=qx+z-1;
217     for i:=qx to qy do
218       if can[i] then
219       begin
220         inc(q1);
221         tw[q1]:=q[i];
222       end
223       else begin
224         inc(q2);
225         tw[q2]:=q[i];
226       end;
227     for i:=qx to qy do
228       q[i]:=tw[i];
229     for i:=1 to tot do
230     begin
231       s:=st[i];
232       v[s]:=false;
233       d[s]:=0;
234     end;
235     tot:=0;
236     cdq(opx,f1,qx,q1,l,m);
237     cdq(f1+1,opy,q1+1,qy,m+1,r);
238   end;
239 
240 begin
241   readln(n,m,k);
242   for i:=1 to n-1 do
243   begin
244     readln(x,y);
245     add(x,y);
246     add(y,x);
247   end;
248   dfs(1);
249   for j:=1 to trunc(ln(n)/ln(2))+1 do
250     for i:=1 to n do
251     begin
252       x:=anc[i,j-1];
253       anc[i,j]:=anc[x,j-1];
254     end;
255 
256   t:=0;
257   for i:=1 to m do
258   begin
259     readln(x,y,z);
260     if a[x]>a[y] then swap(x,y);
261     if a[y]<=b[x] then
262     begin
263       xx:=jump(y,dep[x]+1);
264       if a[xx]<>1 then open(1,a[xx]-1,a[y],b[y],z);
265       if b[xx]<n then open(a[y],b[y],b[xx]+1,n,z);
266     end
267     else open(a[x],b[x],a[y],b[y],z);
268     c[i]:=z;
269   end;
270   sortc(1,m);
271   sortw(1,t);
272   for i:=1 to k do
273   begin
274     readln(x,y,z);
275     if a[x]>a[y] then swap(x,y);
276     q[i].x:=a[x]; q[i].y:=a[y]; q[i].id:=i; q[i].z:=z;
277   end;
278   sortq(1,k);
279   cdq(1,t,1,k,1,m);
280   for i:=1 to k do
281     writeln(ans[i]);
282 end.
View Code
原文地址:https://www.cnblogs.com/phile/p/4490782.html