【BZOJ2874】训练士兵(主席树)
题意:有一个N*M的矩阵,给出一些形如(x1,y1,x2,y2,s)的操作,代表(x1,y1)到(x2,y2)都被加上了s这个数
现在有一些强制在线的询问,询问(x1,y1)到(x2,y2)的和
对于100%的数据 n,m<=10^8,k<=40000,q<=100000;
思路:将操作(x1,y1,x2,y2,s)差分成
(x1,y1)+s
(x1,y2+1)-s
(x2+1,y1)-s
(x2+1,y2+1)+s
四个点
询问(x,y)等价于
\[\sum_{i=1}^x \sum_{j=1}^y \ a[i,j]*(x+1)*(y+1)-a[i,j]*i*(y+1)-a[i,j]*j*(x+1)+a[i,j]*i*j \]
证明如下:
可以看出只需维护a[i,j],a[i,j]*i,a[i,j]*j,a[i,j]*i*j四个值的二维前缀和
从左到右,从上到下排序并离散化,对每一行建立一棵主席树表示左上角的前缀和,
询问时在主席树中查找一段从头开始的前缀和即可
1 var t:array[0..6000000,1..6]of int64; 2 root:array[0..600000]of int64; 3 c:array[1..300000,1..3]of int64; 4 cx,cy:array[1..300000]of int64; 5 n,m,i,j,u,k,cnt,u1,u2,k1,q1,tmp,x,y:longint; 6 ans,x1,y1,x2,y2:int64; 7 8 procedure swap(var x,y:int64); 9 var t:int64; 10 begin 11 t:=x; x:=y; y:=t; 12 end; 13 14 procedure qsortx(l,r:longint); 15 var i,j,mid:longint; 16 begin 17 i:=l; j:=r; mid:=cx[(l+r)>>1]; 18 repeat 19 while mid>cx[i] do inc(i); 20 while mid<cx[j] do dec(j); 21 if i<=j then 22 begin 23 swap(cx[i],cx[j]); 24 inc(i); dec(j); 25 end; 26 until i>j; 27 if l<j then qsortx(l,j); 28 if i<r then qsortx(i,r); 29 end; 30 31 procedure qsorty(l,r:longint); 32 var i,j,mid:longint; 33 begin 34 i:=l; j:=r; mid:=cy[(l+r)>>1]; 35 repeat 36 while mid>cy[i] do inc(i); 37 while mid<cy[j] do dec(j); 38 if i<=j then 39 begin 40 swap(cy[i],cy[j]); 41 inc(i); dec(j); 42 end; 43 until i>j; 44 if l<j then qsorty(l,j); 45 if i<r then qsorty(i,r); 46 end; 47 48 function hashx(x:longint):longint; 49 var l,r,mid,last:longint; 50 begin 51 l:=1; r:=u1; last:=0; 52 while l<=r do 53 begin 54 mid:=(l+r)>>1; 55 if x>=cx[mid] then begin last:=mid; l:=mid+1; end 56 else r:=mid-1; 57 end; 58 exit(last); 59 end; 60 61 function hashy(x:longint):longint; 62 var l,r,mid,last:longint; 63 begin 64 l:=1; r:=u2; last:=0; 65 while l<=r do 66 begin 67 mid:=(l+r)>>1; 68 if x>=cy[mid] then begin last:=mid; l:=mid+1; end 69 else r:=mid-1; 70 end; 71 exit(last); 72 end; 73 74 procedure qsort(l,r:longint); 75 var i,j,mid1,mid2:longint; 76 begin 77 i:=l; j:=r; mid1:=c[(l+r)>>1,1]; mid2:=c[(l+r)>>1,2]; 78 repeat 79 while (mid1>c[i,1])or((mid1=c[i,1])and(mid2>c[i,2])) do inc(i); 80 while (mid1<c[j,1])or((mid1=c[j,1])and(mid2<c[j,2])) do dec(j); 81 if i<=j then 82 begin 83 swap(c[i,1],c[j,1]); 84 swap(c[i,2],c[j,2]); 85 swap(c[i,3],c[j,3]); 86 inc(i); dec(j); 87 end; 88 until i>j; 89 if l<j then qsort(l,j); 90 if i<r then qsort(i,r); 91 end; 92 93 function query(p,l,r,x,y:longint):int64; 94 var mid:longint; 95 begin 96 if x=0 then exit(0); 97 if p=0 then exit(0); 98 if x>=r then exit(t[p,y]); 99 mid:=(l+r)>>1; 100 if x<=mid then exit(query(t[p,5],l,mid,x,y)) 101 else exit(t[t[p,5],y]+query(t[p,6],mid+1,r,x,y)); 102 end; 103 104 function ask(x,y:longint):int64; 105 var x1,y1:longint; 106 begin 107 x1:=hashx(x); y1:=hashy(y); 108 ask:=0; 109 ask:=ask+query(root[x1],1,u2,y1,1)*(x+1)*(y+1); 110 ask:=ask-query(root[x1],1,u2,y1,2)*(y+1); 111 ask:=ask-query(root[x1],1,u2,y1,3)*(x+1); 112 ask:=ask+query(root[x1],1,u2,y1,4); 113 end; 114 115 procedure update(var p:int64;l,r,x:longint;v:int64;x1,y1:longint); 116 var mid:longint; 117 begin 118 inc(cnt); t[cnt]:=t[p]; 119 p:=cnt; 120 t[cnt,1]:=t[cnt,1]+v; 121 t[cnt,2]:=t[cnt,2]+v*x1; 122 t[cnt,3]:=t[cnt,3]+v*y1; 123 t[cnt,4]:=t[cnt,4]+v*x1*y1; 124 if l=r then exit; 125 mid:=(l+r)>>1; 126 if x<=mid then update(t[p,5],l,mid,x,v,x1,y1) 127 else update(t[p,6],mid+1,r,x,v,x1,y1); 128 end; 129 130 begin 131 assign(input,'bzoj2874.in'); reset(input); 132 assign(output,'bzoj2874.out'); rewrite(output); 133 readln(n,m,k1,q1); 134 k:=0; 135 for i:=1 to k1 do 136 begin 137 read(x1); read(x2); read(y1); read(y2); read(tmp); 138 inc(k); c[k,1]:=x1; c[k,2]:=y1; c[k,3]:=tmp; 139 inc(k); c[k,1]:=x1; c[k,2]:=y2+1; c[k,3]:=-tmp; 140 inc(k); c[k,1]:=x2+1; c[k,2]:=y1; c[k,3]:=-tmp; 141 inc(k); c[k,1]:=x2+1; c[k,2]:=y2+1; c[k,3]:=tmp; 142 inc(u); cx[u]:=x1; cy[u]:=y1; 143 inc(u); cx[u]:=x2+1; cy[u]:=y2+1; 144 end; 145 qsortx(1,u); qsorty(1,u); 146 u1:=1; 147 for i:=2 to u do 148 if cx[i]<>cx[u1] then begin inc(u1); cx[u1]:=cx[i]; end; 149 u2:=1; 150 for i:=2 to u do 151 if cy[i]<>cy[u2] then begin inc(u2); cy[u2]:=cy[i]; end; 152 153 qsort(1,k); 154 j:=1; 155 for i:=1 to u1 do 156 begin 157 root[i]:=root[i-1]; 158 while (j<=k)and(hashx(c[j,1])=i) do 159 begin 160 update(root[i],1,u2,hashy(c[j,2]),c[j,3],c[j,1],c[j,2]); 161 inc(j); 162 end; 163 end; 164 for i:=1 to q1 do 165 begin 166 readln(x,y); 167 x1:=ans mod n+1; x2:=(ans+x) mod n+1; if x1>x2 then swap(x1,x2); 168 y1:=ans mod m+1; y2:=(ans+y) mod m+1; if y1>y2 then swap(y1,y2); 169 ans:=ask(x2,y2)-ask(x1-1,y2)-ask(x2,y1-1)+ask(x1-1,y1-1); 170 writeln(ans); 171 end; 172 close(input); 173 close(output); 174 end.
null