【Hihocoder1034】毁灭者问题(splay,树状数组)

题意:

假设你拥有 n 个魔法单位,他们从左到有站在一行,编号从 1 到 n。 每个单位拥有三项属性:

 

  • si: 初始法力。

  • mi: 最大法力上限。

  • ri: 每秒中法力回复速度。

 

现在你操纵一个毁灭者,有 m 个操作,t l r,表示时刻 t,毁灭者对所有编号从 l 到 r 的单位,使用了魔法吸收。操作按照时间顺序给出,计算毁灭者一共吸收了多少法力。

 

n<=10^5 s[i],m[i],r[i]<=10^5 m<=10^5 maxtime<=10^9

 

思路:RYZ作业

因为每个人的回复速度不同且都有上限,所以不能用线段树完成

转换思路,不能维护每个人的魔法值,就应该维护时间点与时间间隔

考虑单位i,假设它回满的时间长为man,那么它对答案的贡献就是s1*r[i]+s2*m[i]

其中s1为<man的间隔的总和,s2为>=man的间隔的个数

现在问题转化成:

时间间隔需要维护插入,删除,子树大小和子树和,平衡树即可

时间点需要维护前驱,后继,插入,删除,我用树状数组,每次操作O(log^2 n),如果用平衡树可以达到O(log n)

需要注意的是查询[0,man-1]这段区间时需要找到第一个>man-1的位置,而查询[man,oo]这段时需要找到最后一个<man的位置,所以rank函数不能共用

总复杂度O(m log^2 n),维护时间时使用平衡树可以达到O(m log n)

不过m,n只有100000,煮不在糊

话说这个OJ不能用P交,那只能用对拍了

 

  1 var t:array[0..300000,0..1]of longint;
  2     size,fa,l1,l2,l3,r1,r2,r3,
  3     x,y,z,c,time,t1,t2,t3,s,m,r,q:array[0..300000]of longint;
  4     sum,num:array[0..300000]of int64;
  5     n,i,que,head,tail,up,k,tot,root,cnt,k1,k2,man,kk,tmp,j:longint;
  6     ans1,ans2,s1,s2:int64;
  7     flag:boolean;
  8 
  9 procedure swap(var x,y:longint);
 10 var t:longint;
 11 begin
 12  t:=x; x:=y; y:=t;
 13 end;
 14 
 15 procedure pushup(x:longint);
 16 var l,r:longint;
 17 begin
 18  l:=t[x,0]; r:=t[x,1];
 19  size[x]:=size[l]+size[r]+1;
 20 // size[x]:=size[l]+size[r];
 21  sum[x]:=sum[l]+sum[r];
 22  if (num[x]<>maxlongint)and(num[x]<>-1) then sum[x]:=sum[x]+num[x];
 23 end;
 24 
 25 procedure rotate(x:longint;var k:longint);
 26 var y,z,l,r:longint;
 27 begin
 28  y:=fa[x]; z:=fa[y];
 29  if t[y,0]=x then l:=0
 30   else l:=1;
 31  r:=l xor 1;
 32  if y<>k then
 33  begin
 34   if t[z,0]=y then t[z,0]:=x
 35    else t[z,1]:=x;
 36  end
 37   else k:=x;
 38  fa[x]:=z; fa[y]:=x; fa[t[x,r]]:=y;
 39  t[y,l]:=t[x,r]; t[x,r]:=y;
 40  pushup(y);
 41  pushup(x);
 42 end;
 43 
 44 procedure splay(x:longint;var k:longint);
 45 var y,z:longint;
 46 begin
 47  while x<>k do
 48  begin
 49   y:=fa[x]; z:=fa[y];
 50   if y<>k then
 51   begin
 52    if (t[y,0]=x)xor(t[z,0]=y) then rotate(x,k)
 53     else rotate(y,k);
 54   end
 55    else k:=x;
 56   rotate(x,k);
 57  end;
 58 end;
 59 
 60 function kth(x:longint):longint;
 61 var k,tmp:longint;
 62 begin
 63  k:=root;
 64  while true do
 65  begin
 66   tmp:=size[t[k,0]]+1;
 67   if tmp=x then exit(k);
 68   if tmp>x then k:=t[k,0]
 69    else
 70    begin
 71     k:=t[k,1]; x:=x-tmp;
 72    end;
 73  end;
 74 end;
 75 
 76 function pred(x:longint):longint;
 77 var k,last:longint;
 78 begin
 79  k:=root; last:=num[root];
 80  while k<>0 do
 81  begin
 82   if num[k]<x then begin last:=num[k]; k:=t[k,1]; end
 83    else k:=t[k,0];
 84  end;
 85  exit(last);
 86 end;
 87 
 88 function succ(x:longint):longint;
 89 var k,last:longint;
 90 begin
 91  k:=root; last:=maxlongint;
 92  while k<>0 do
 93  begin
 94   if num[k]>x then begin last:=num[k]; k:=t[k,0]; end
 95    else k:=t[k,1];
 96  end;
 97  exit(last);
 98 end;
 99 
100 function rank(x:longint):longint;
101 var k:longint;
102 begin
103  if x=-1 then exit(1);
104  x:=pred(x);
105  k:=root; rank:=0;
106  while k>0 do
107  begin
108   if num[k]<=x then begin rank:=rank+size[t[k,0]]+1; k:=t[k,1]; end
109    else k:=t[k,0];
110  end;
111  inc(rank);
112 end;
113 
114 procedure ins(x:longint);
115 var k,l,r:longint;
116 begin
117  if x=0 then exit;
118 // if x<0 then begin writeln('error ',i);  exit; end;
119  k:=rank(x);
120  l:=kth(k-1);
121  r:=kth(k);
122  splay(l,root);
123  splay(r,t[root,1]);
124  k:=t[root,1];
125  inc(cnt); t[k,0]:=cnt; fa[cnt]:=k;
126  size[cnt]:=1;  num[cnt]:=x; sum[cnt]:=x;
127  inc(tot);
128 // writeln('ins ',x,' ',tot);
129 end;
130 
131 procedure del(x:longint);
132 var k,l,r,k1,k2:longint;
133 begin
134  if x=0 then exit;
135  k:=rank(x);
136  l:=kth(k-1);
137  r:=kth(k+1);
138  splay(l,root);
139  splay(r,t[root,1]);
140  k1:=t[root,1]; k2:=t[k1,0];
141  size[k1]:=size[t[k1,1]]+1;
142  //sum[k1]:=sum[t[k1,1]]+num[k1];
143  sum[k1]:=sum[t[k1,1]];
144  if (num[k1]<>maxlongint)and(num[k1]<>-1) then sum[k1]:=sum[k1]+num[k1];
145  fa[k2]:=0; sum[k2]:=0;  size[k2]:=0;
146  t[k2,0]:=0; t[k2,1]:=0; num[k2]:=0;
147  t[k1,0]:=0;
148  dec(tot);
149  //writeln('del ',x,' ',tot);
150 end;
151 
152 function lowbit(x:longint):longint;
153 begin
154  exit(x and (-x));
155 end;
156 
157 function sumbit(x:longint):longint;
158 begin
159  sumbit:=0;
160  while x>0 do
161  begin
162   sumbit:=sumbit+q[x];
163   x:=x-lowbit(x);
164  end;
165 end;
166 
167 procedure add(x,s:longint);
168 begin
169  while x<=200000 do
170  begin
171   q[x]:=q[x]+s;
172   x:=x+lowbit(x);
173  end;
174 end;
175 
176 procedure qsort1(l,r:longint);
177 var mid,i,j:longint;
178 begin
179  i:=l; j:=r; mid:=l1[(l+r)>>1];
180  repeat
181   while mid>l1[i] do inc(i);
182   while mid<l1[j] do dec(j);
183   if i<=j then
184   begin
185    swap(l1[i],l1[j]);
186    swap(r1[i],r1[j]);
187    swap(t1[i],t1[j]);
188    inc(i); dec(j);
189   end;
190  until i>j;
191  if l<j then qsort1(l,j);
192  if i<r then qsort1(i,r);
193 end;
194 
195 procedure qsort2(l,r:longint);
196 var mid,i,j:longint;
197 begin
198  i:=l; j:=r; mid:=r2[(l+r)>>1];
199  repeat
200   while mid>r2[i] do inc(i);
201   while mid<r2[j] do dec(j);
202   if i<=j then
203   begin
204    swap(l2[i],l2[j]);
205    swap(r2[i],r2[j]);
206    swap(t2[i],t2[j]);
207    inc(i); dec(j);
208   end;
209  until i>j;
210  if l<j then qsort2(l,j);
211  if i<r then qsort2(i,r);
212 end;
213 
214 function findkth(x:longint):longint;
215 var l,r,mid,last,tmp:longint;
216 begin
217  l:=1; r:=200000; last:=0;
218  while l<=r do
219  begin
220   mid:=(l+r)>>1;
221   tmp:=sumbit(mid);
222   {if tmp<=x then begin last:=mid; l:=mid+1; end
223    //else r:=mid-1;     }
224   if tmp>x then r:=mid-1
225    else if tmp<x then begin last:=mid;  l:=mid+1 end
226     else if tmp=x then begin last:=mid; r:=mid-1; end;
227 
228  end;
229  if sumbit(last)<x then inc(last);
230  exit(last);
231 end;
232 
233 {function findkth(x:longint):longint;
234 var ret,p:longint;
235 begin
236  p:=1<<17; ret:=0;
237  while p>0 do
238  begin
239   if q[ret+p]<=x then
240   begin
241    ret:=ret+p;
242    x:=x-q[ret];
243   end;
244   p:=p>>1;
245  end;
246  exit(ret);
247 end;  }
248 
249 function hash(x:longint):longint;
250 var l,r,mid,last:longint;
251 begin
252  l:=1; r:=up; last:=0;
253  while l<=r do
254  begin
255   mid:=(l+r)>>1;
256   if time[mid]=x then exit(mid)
257    else if time[mid]>x then r:=mid-1
258     else l:=mid+1;
259  end;
260  //exit(last);
261 end;
262 
263 function querymn(x:longint):int64;
264 var k1,k2:longint;
265 begin
266  k1:=kth(1);
267  k2:=kth(rank(succ(x-1)));
268  splay(k1,root);
269  splay(k2,t[root,1]);
270  exit(sum[t[k2,0]]);
271 // exit(size[t[k2,0]]);
272 end;
273 
274 function querymx(x:longint):int64;
275 var k1,k2,s:longint;
276 begin
277  k1:=pred(x);
278  k:=root; s:=0;
279  while k>0 do
280  begin
281   if num[k]<=k1 then begin s:=s+size[t[k,0]]+1; k:=t[k,1]; end
282    else k:=t[k,0];
283  end;
284 
285  k1:=kth(s);
286  k2:=kth(tot);
287  splay(k1,root);
288  splay(k2,t[root,1]);
289  exit(size[t[k2,0]]);
290 end;
291 
292 function min(x,y:longint):longint;
293 begin
294  if x<y then exit(x);
295  exit(y);
296 end;
297 
298 function max(x,y:longint):longint;
299 begin
300  if x>y then exit(x);
301  exit(y);
302 end;
303 
304 begin
305  assign(input,'data.in'); reset(input);
306  assign(output,'hihocoder1034.out'); rewrite(output);
307  readln(n);
308  for i:=1 to n do read(s[i],m[i],r[i]);
309  readln(que);
310  for i:=1 to que do
311  begin
312   read(x[i],y[i],z[i]);
313   inc(x[i]);
314  end;
315  l1:=y; r1:=z; t1:=x;
316  l2:=y; r2:=z; t2:=x;
317  l3:=y; r3:=z; t3:=x;
318  qsort1(1,que);
319  qsort2(1,que);
320 
321  if time[1]=1 then begin time[1]:=1; up:=1; end
322   else begin time[1]:=1; time[2]:=t3[1]; up:=2; end;
323  for i:=2 to que do
324   if t3[i]<>time[up] then begin inc(up); time[up]:=t3[i]; end;
325  inc(up); time[up]:=maxlongint;
326  add(1,1);
327  add(200000,1);
328  num[1]:=maxlongint; size[1]:=2;
329  t[1,0]:=2;
330  num[2]:=-1; fa[2]:=1; size[2]:=1;
331  root:=1; cnt:=2; tot:=2;
332  //for i:=1 to que do c[i]:=hash(x[i]);
333  head:=1; tail:=1;
334 
335  for i:=1 to n do
336  begin
337 
338 
339   if r[i]=0 then man:=maxlongint-1
340    else
341    begin
342     if m[i] mod r[i]=0 then man:=m[i] div r[i]
343      else man:=m[i] div r[i]+1;
344    end;
345 
346   while (head<=que)and(i>=l1[head]) do
347   begin
348    kk:=hash(t1[head]);
349    k:=sumbit(kk-1)+1;
350    k1:=findkth(k-1);
351    k2:=findkth(k);
352    ins(t1[head]-time[k1]);
353    if k2<>200000 then ins(time[k2]-t1[head]);
354    if k2<>200000 then del(time[k2]-time[k1]);
355    add(kk,1); inc(head);
356   end;
357 
358   while (tail<=que)and(i>r2[tail]) do
359   begin
360    kk:=hash(t2[tail]);
361    k:=sumbit(kk-1)+1;
362    k1:=findkth(k-1);
363    k2:=findkth(k+1);
364    if k2<>200000 then ins(time[k2]-time[k1]);
365    del(t2[tail]-time[k1]);
366    if k2<>200000 then del(time[k2]-t2[tail]);
367    add(kk,-1); inc(tail);
368   end;
369 
370 
371   s1:=querymn(man);
372   s2:=querymx(man);
373   ans1:=ans1+s1*r[i]+s2*m[i];
374 
375  { s1:=0;
376   for j:=1 to cnt do
377    if (num[j]<>0)and(num[j]<man) then inc(s1);
378   s2:=0;
379   for j:=1 to cnt do
380    if (num[j]<>0)and(num[j]>=man) then inc(s2);
381 
382   ans2:=ans2+s1*r[i]+s2*m[i];                   }
383   k:=findkth(2);
384   if k<>200000 then
385   begin
386    tmp:=time[k];
387    s1:=tmp-1;
388    s1:=s1*r[i];
389    if m[i]<s1 then s1:=m[i]; //start with 0
390    s2:=tmp-1;
391    s2:=s2*r[i]+s[i];
392    if m[i]<s2 then s2:=m[i]; //start with s[i]
393    ans1:=ans1-s1+s2;
394   end;
395  // writeln(ans1);
396   //writeln(ans2);
397 
398  end;
399 
400  writeln(ans1);
401 
402  close(input);
403  close(output);
404 end.

 

posted on 2017-02-12 17:25  myx12345  阅读(421)  评论(0编辑  收藏  举报

导航