【BZOJ3110】K大数查询(权值线段树套线段树+标记永久化,整体二分)

题意:有N个位置,M个操作。操作有两种,每次操作

如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c

如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少。


N,M<=50000,N,M<=50000

a<=b<=N

1操作中abs(c)<=N

2操作中c<=Maxlongint

思路:这道题如果外层是位置的话就需要在外层区间更新 并不会写

所以需要外层权值,内层位置

然而常数太渣,BZOJ上过不去

并不想(会)写标记永久化

  1 var t:array[0..20000000]of record
  2                             l,r:longint;
  3                             a,s:int64;
  4                            end;
  5     op,x,y,z,d:array[1..200000]of longint;
  6     root:array[0..1000000]of longint;
  7     n,m,up,i,tmp,n1,cnt:longint;
  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  
 16 function query(l,r,x,y,p:longint):int64;
 17 var mid,k:longint;
 18     tmp:int64;
 19 begin
 20  if p=0 then exit(0);
 21  mid:=(l+r)>>1;
 22  if (t[p].a>0)and(l<r) then
 23  begin
 24   tmp:=t[p].a;
 25   if t[p].l=0 then begin inc(cnt); t[p].l:=cnt; end;
 26   k:=t[p].l;
 27   t[k].a:=t[k].a+tmp;
 28   t[k].s:=t[k].s+tmp*(mid-l+1);
 29   if t[p].r=0 then begin inc(cnt); t[p].r:=cnt; end;
 30   k:=t[p].r;
 31   t[k].a:=t[k].a+tmp;
 32   t[k].s:=t[k].s+tmp*(r-mid);
 33   t[p].a:=0;
 34  end;
 35  if (l>=x)and(r<=y) then exit(t[p].s);
 36  query:=0;
 37  if x<=mid then query:=query+query(l,mid,x,y,t[p].l);
 38  if y>mid then query:=query+query(mid+1,r,x,y,t[p].r);
 39  
 40 end;
 41  
 42 procedure update(l,r,x,y:longint;var p:longint);
 43 var mid,k:longint;
 44     tmp:int64;
 45 begin
 46  if p=0 then begin inc(cnt); p:=cnt; end;
 47  mid:=(l+r)>>1;
 48  if (t[p].a>0)and(l<r) then
 49  begin
 50   tmp:=t[p].a;
 51   if t[p].l=0 then begin inc(cnt); t[p].l:=cnt; end;
 52   k:=t[p].l;
 53   t[k].a:=t[k].a+tmp;
 54   t[k].s:=t[k].s+tmp*(mid-l+1);
 55   if t[p].r=0 then begin inc(cnt); t[p].r:=cnt; end;
 56   k:=t[p].r;
 57   t[k].a:=t[k].a+tmp;
 58   t[k].s:=t[k].s+tmp*(r-mid);
 59   t[p].a:=0;
 60  end;
 61  if (l>=x)and(r<=y) then
 62  begin
 63   t[p].a:=t[p].a+1;
 64   t[p].s:=t[p].s+r-l+1;
 65   exit;
 66  end;
 67  if x<=mid then update(l,mid,x,y,t[p].l);
 68  if y>mid then update(mid+1,r,x,y,t[p].r);
 69  
 70  t[p].s:=t[t[p].l].s+t[t[p].r].s;
 71 end;
 72  
 73 procedure add(a,b,c:longint);
 74 var l,r,k,mid:longint;
 75 begin
 76  l:=1; r:=n+n+1; k:=1;
 77  while l<r do
 78  begin
 79   mid:=(l+r)>>1;
 80   update(1,n,a,b,root[k]);
 81   if c<=mid then
 82   begin
 83    r:=mid; k:=k<<1;
 84   end
 85    else
 86    begin
 87     l:=mid+1; k:=(k<<1)+1;
 88    end;
 89  end;
 90  update(1,n,a,b,root[k]);
 91 end;
 92  
 93 function ask(a,b:longint;c:int64):longint;
 94 var l,r,mid,k:longint;
 95     tmp:int64;
 96 begin
 97  l:=1; r:=n+n+1; k:=1;
 98  while l<r do
 99  begin
100   mid:=(l+r)>>1;
101   tmp:=query(1,n,a,b,root[k<<1]);
102   if tmp>=c then
103   begin
104    r:=mid; k:=k<<1;
105   end
106    else
107    begin
108     l:=mid+1; k:=(k<<1)+1;
109     c:=c-tmp;
110    end;
111  end;
112  exit(l);
113 end;
114  
115 begin
116  
117  readln(n,m);
118  for i:=1 to m do read(op[i],x[i],y[i],z[i]);
119  
120  for i:=1 to m do
121   if op[i]=1 then add(x[i],y[i],n+1-z[i])
122  
123    else writeln(n+1-ask(x[i],y[i],z[i]));
124  
125  
126  
127 end.

2017.3.19

想了想还是学一波奇技淫巧

需要注意的是标记永久化只能用(l=x)and(r=y)的写法写

  1 var t:array[0..20000000]of record
  2                             l,r:longint;
  3                             a,s:int64;
  4                            end;
  5     op,x,y,z,d:array[1..200000]of longint;
  6     root:array[0..1000000]of longint;
  7     n,m,up,i,tmp,n1,cnt:longint;
  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(l,r,p:longint);
 16 begin
 17  t[p].s:=t[t[p].l].s+t[t[p].r].s+t[p].a*(r-l+1);
 18 end;
 19   
 20 function query(l,r,x,y,p:longint):int64;
 21 var mid:longint;
 22     ans:int64;
 23 begin
 24  if p=0 then exit(0);
 25  if (l=x)and(r=y) then exit(t[p].s);
 26  mid:=(l+r)>>1;
 27  query:=0;
 28  ans:=t[p].a*(y-x+1);
 29        if y<=mid then exit(query(l,mid,x,y,t[p].l)+ans)
 30   else if x>mid then exit(query(mid+1,r,x,y,t[p].r)+ans)
 31   else exit(query(l,mid,x,mid,t[p].l)+query(mid+1,r,mid+1,y,t[p].r)+ans);
 32 end;
 33   
 34 procedure update(l,r,x,y:longint;var p:longint);
 35 var mid,k:longint;
 36     tmp:int64;
 37 begin
 38  if p=0 then begin inc(cnt); p:=cnt; end;
 39  mid:=(l+r)>>1;
 40  if (l=x)and(r=y) then
 41  begin
 42   t[p].a:=t[p].a+1;
 43   t[p].s:=t[p].s+r-l+1;
 44   exit;
 45  end;
 46       if y<=mid then update(l,mid,x,y,t[p].l)
 47  else if x>mid then update(mid+1,r,x,y,t[p].r)
 48  else
 49  begin
 50   update(l,mid,x,mid,t[p].l);
 51   update(mid+1,r,mid+1,y,t[p].r);
 52  end;
 53  pushup(l,r,p);
 54 end;
 55   
 56 procedure add(a,b,c:longint);
 57 var l,r,k,mid:longint;
 58 begin
 59  l:=1; r:=n+n+1; k:=1;
 60  while l<r do
 61  begin
 62   mid:=(l+r)>>1;
 63   update(1,n,a,b,root[k]);
 64   if c<=mid then
 65   begin
 66    r:=mid; k:=k<<1;
 67   end
 68    else
 69    begin
 70     l:=mid+1; k:=(k<<1)+1;
 71    end;
 72  end;
 73  update(1,n,a,b,root[k]);
 74 end;
 75   
 76 function ask(a,b:longint;c:int64):longint;
 77 var l,r,mid,k:longint;
 78     tmp:int64;
 79 begin
 80  l:=1; r:=n+n+1; k:=1;
 81  while l<r do
 82  begin
 83   mid:=(l+r)>>1;
 84   tmp:=query(1,n,a,b,root[k<<1]);
 85   if tmp>=c then
 86   begin
 87    r:=mid; k:=k<<1;
 88   end
 89    else
 90    begin
 91     l:=mid+1; k:=(k<<1)+1;
 92     c:=c-tmp;
 93    end;
 94  end;
 95  exit(l);
 96 end;
 97    
 98 begin
 99    
100  readln(n,m);
101  for i:=1 to m do read(op[i],x[i],y[i],z[i]);
102    
103  for i:=1 to m do
104   if op[i]=1 then add(x[i],y[i],n+1-z[i])
105    
106    else writeln(n+1-ask(x[i],y[i],z[i]));
107   
108   
109   
110 end.

 整体二分是二分答案,CDQ分治是二分操作序列

比树套树快2倍

  1 var a,b:array[1..100000]of record
  2                           l,r,id,op:longint;
  3                           w:int64;
  4                          end;
  5     s1,s2:array[1..100000]of int64;
  6     flag,ans:array[1..100000]of longint;
  7     n,m,i,cnt:longint;
  8 
  9 function lowbit(x:longint):longint;
 10 begin
 11  exit(x and (-x));
 12 end;
 13 
 14 procedure add(x,y:longint);
 15 var i:longint;
 16 begin
 17  i:=x;
 18  while i<=n do
 19  begin
 20   s1[i]:=s1[i]+y;
 21   s2[i]:=s2[i]+y*x;
 22   i:=i+lowbit(i);
 23  end;
 24 end;
 25 
 26 procedure update(a,b,c:longint);
 27 begin
 28  add(a,c); add(b+1,-c);
 29 end;
 30 
 31 function query(x:longint):int64;
 32 var i:longint;
 33 begin
 34  i:=x; query:=0;
 35  while i>0 do
 36  begin
 37   query:=query+s1[i]*(x+1)-s2[i];
 38   i:=i-lowbit(i);
 39  end;
 40 end;
 41 
 42 function ask(a,b:longint):int64;
 43 begin
 44  exit(query(b)-query(a-1));
 45 end;
 46 
 47 procedure solve(x,y,l,r:longint);
 48 var i,mid,pre,now:longint;
 49     tmp:int64;
 50 begin
 51  if l=r then
 52  begin
 53   for i:=x to y do
 54    if a[i].op=2 then ans[a[i].id]:=l;
 55   exit;
 56  end;
 57  mid:=(l+r)>>1;
 58  pre:=x; now:=x;
 59  for i:=x to y do
 60   if a[i].op=1 then
 61   begin
 62    if a[i].w<=mid then
 63    begin
 64     update(a[i].l,a[i].r,1);
 65     flag[i]:=0;
 66     inc(now);
 67    end
 68     else flag[i]:=1;
 69   end
 70    else
 71    begin
 72     tmp:=ask(a[i].l,a[i].r);
 73     if tmp>=a[i].w then
 74     begin
 75      inc(now); flag[i]:=0;
 76     end
 77      else
 78      begin
 79       flag[i]:=1;
 80       a[i].w:=a[i].w-tmp;
 81      end;
 82    end;
 83  for i:=x to y do
 84   if (a[i].op=1)and(a[i].w<=mid) then update(a[i].l,a[i].r,-1);
 85  for i:=x to y do
 86   if flag[i]=1 then
 87   begin
 88    b[now]:=a[i]; inc(now);
 89   end
 90    else
 91    begin
 92     b[pre]:=a[i]; inc(pre);
 93    end;
 94  for i:=x to y do a[i]:=b[i];
 95  solve(x,pre-1,l,mid);
 96  solve(pre,y,mid+1,r);
 97 end;
 98 
 99 begin
100  assign(input,'bzoj3110.in'); reset(input);
101  assign(output,'bzoj3110.out'); rewrite(output);
102  read(n,m);
103  for i:=1 to m do
104  begin
105   read(a[i].op,a[i].l,a[i].r,a[i].w);
106   if a[i].op=1 then a[i].w:=n-a[i].w+1
107    else
108    begin
109     inc(cnt); a[i].id:=cnt;
110    end;
111  end;
112  solve(1,m,1,2*n+1);
113  for i:=1 to cnt do writeln(n-ans[i]+1);
114  close(input);
115  close(output);
116 end.

 

posted on 2017-03-17 16:08  myx12345  阅读(177)  评论(0编辑  收藏  举报

导航