2877: [Noi2012]魔幻棋盘 - BZOJ

Description
Input

第一行为两个正整数N,M,表示棋盘的大小。 第二行为两个正整数X,Y,表示棋盘守护者的位置。 第三行仅有一个正整数T,表示棋盘守护者将进行次操作。 接下来N行,每行有M个正整数,用来描述初始时棋盘上每个位置的数。 接下来T行,按操作的时间顺序给出T次操作。每行描述一次操作,以一个数字0或1开头: 若以数字0开头,表示此操作为询问,随后会有四个非负整数x1,y1,x2,y2,表示询问的区域是以棋盘守护者的位置为基础向上扩展x1行,向下扩展y1行,向左扩展x2列,向右扩展y2列得到的矩形区域(详见样例)。 若以数字1开头,表示此操作为修改,随后会有四个正整数x1,y1,x2,y2和一个整数c,表示修改区域的上、下边界分别为第x1,x2行,左、右边界分别为第y1,y2列(详见样例),在此矩形区域内的所有数统一加上c(注意c可能为负数)。
Output


 对于每次询问操作,每行输出一个数,表示该区域内所有数的最大公约数。
Sample Input
2 2
1 1
4
6 12
18 24
0 0 0 1 0
1 1 1 1 2 6
1 2 1 2 2 6
0 0 0 1 1


Sample Output
6 6

 

 

一开始觉得直接放在一个二维线段树上,但是太麻烦了(打了20多个if,没有力气debug)

想了一晚上,果断改成两个一维的和一个二维的,好打多了,早上改了一下就A了

首先按点(x,y)把棋盘化成4个部分,然后就相当于只要得到前缀gcd,所以横着差分一下,竖着差分一下,然后把4个矩形拼在一起就变成了正解里的那个奇怪的矩阵

第一次打二维线段树

  1 const
  2     maxn=500000;
  3 type
  4     node=record
  5         l,r,lc,rc:longint;
  6         a:int64;
  7     end;
  8 var
  9     a,b:array[0..maxn]of int64;
 10     f,f2:array[0..maxn*4]of node;
 11     n,m,t,x,y,tot,cnt,ll,rr,root1,root2:longint;
 12  
 13 function calc(a,b:longint):longint;
 14 begin
 15     exit((a-1)*m+b);
 16 end;
 17  
 18 function gcd(a,b:int64):int64;
 19 begin
 20     if b=0 then exit(a);
 21     exit(gcd(b,a mod b));
 22 end;
 23  
 24 procedure new(x,y,z:longint);
 25 begin
 26     f2[x].a:=gcd(abs(f2[y].a),abs(f2[z].a));
 27     if f2[x].l=f2[x].r then exit;
 28     new(f2[x].lc,f2[y].lc,f2[z].lc);
 29     new(f2[x].rc,f2[y].rc,f2[z].rc);
 30 end;
 31  
 32 procedure build2(l,r:longint);
 33 var
 34     now,mid:longint;
 35 begin
 36     if l>r then exit;
 37     inc(cnt);now:=cnt;
 38     f2[now].l:=l;f2[now].r:=r;
 39     if l=r then
 40     begin
 41         if ll=rr then f2[now].a:=b[calc(ll,l)];
 42         exit;
 43     end;
 44     mid:=(l+r)>>1;
 45     f2[now].lc:=cnt+1;
 46     build2(l,mid);
 47     f2[now].rc:=cnt+1;
 48     build2(mid+1,r);
 49     if ll=rr then f2[now].a:=gcd(abs(f2[f2[now].lc].a),abs(f2[f2[now].rc].a));
 50 end;
 51  
 52 procedure build(l,r:longint);
 53 var
 54     now,mid:longint;
 55 begin
 56     if l>r then exit;
 57     inc(tot);now:=tot;
 58     f[now].l:=l;f[now].r:=r;
 59     if l=r then
 60     begin
 61         f[now].a:=cnt+1;
 62         ll:=l;rr:=r;
 63         build2(1,m-1);
 64         exit;
 65     end;
 66     mid:=(l+r)>>1;
 67     f[now].lc:=tot+1;
 68     build(l,mid);
 69     f[now].rc:=tot+1;
 70     build(mid+1,r);
 71     f[now].a:=cnt+1;
 72     ll:=l;rr:=r;
 73     build2(1,m-1);
 74     new(f[now].a,f[f[now].lc].a,f[f[now].rc].a);
 75 end;
 76  
 77 function get(now,l,r:longint):int64;
 78 var
 79     mid:longint;
 80 begin
 81     if (f2[now].l>=l) and (f2[now].r<=r) then exit(abs(f2[now].a));
 82     mid:=(f2[now].l+f2[now].r)>>1;
 83     get:=0;
 84     if l<=mid then get:=gcd(get(f2[now].lc,l,r),get);
 85     if r>mid then get:=gcd(get(f2[now].rc,l,r),get);
 86 end;
 87  
 88 function get(now,x1,y1,x2,y2:longint):int64;
 89 var
 90     mid:longint;
 91 begin
 92     if (x1>y1) or (x2>y2) then exit(0);
 93     if (f[now].l>=x1) and (f[now].r<=y1) then exit(get(f[now].a,x2,y2));
 94     get:=0;mid:=(f[now].l+f[now].r)>>1;
 95     if x1<=mid then get:=gcd(get(f[now].lc,x1,y1,x2,y2),get);
 96     if y1>mid then get:=gcd(get(f[now].rc,x1,y1,x2,y2),get);
 97 end;
 98  
 99 procedure new(x,y,z,k:longint);
100 var
101     mid:longint;
102 begin
103     f2[x].a:=gcd(abs(f2[y].a),abs(f2[z].a));
104     if f2[x].l=f2[x].r then exit;
105     mid:=(f2[x].l+f2[x].r)>>1;
106     if k<=mid then new(f2[x].lc,f2[y].lc,f2[z].lc,k)
107     else new(f2[x].rc,f2[y].rc,f2[z].rc,k);
108 end;
109  
110 procedure add(now,x:longint;c:int64);
111 var
112     mid:longint;
113 begin
114     if f2[now].l=f2[now].r then
115     begin
116         inc(f2[now].a,c);
117         exit;
118     end;
119     mid:=(f2[now].l+f2[now].r)>>1;
120     if x<=mid then add(f2[now].lc,x,c)
121     else add(f2[now].rc,x,c);
122     f2[now].a:=gcd(abs(f2[f2[now].lc].a),abs(f2[f2[now].rc].a));
123 end;
124  
125 procedure add(now,x,y:longint;c:int64);
126 var
127     mid:longint;
128 begin
129     if (x<1) or (x>=n) or (y<1) or (y>=m) then exit;
130     if f[now].l=f[now].r then
131     begin
132         add(f[now].a,y,c);
133         exit;
134     end;
135     mid:=(f[now].l+f[now].r)>>1;
136     if x<=mid then add(f[now].lc,x,y,c)
137     else add(f[now].rc,x,y,c);
138     new(f[now].a,f[f[now].lc].a,f[f[now].rc].a,y);
139 end;
140  
141 procedure main;
142 var
143     i,j,k,x1,y1,x2,y2:longint;
144     c:int64;
145 begin
146     read(n,m,x,y,t);
147     for i:=1 to n do
148         for j:=1 to m do
149             read(a[calc(i,j)]);
150     for i:=1 to n-1 do
151         for j:=1 to m-1 do
152             b[calc(i,j)]:=a[calc(i,j)]+a[calc(i+1,j+1)]-a[calc(i,j+1)]-a[calc(i+1,j)];
153     build(1,n-1);
154     ll:=rr+1;
155     root1:=cnt+1;
156     build2(1,n);
157     root2:=cnt+1;
158     build2(1,m);
159     for i:=1 to n do
160         if i=x then add(root1,x,a[calc(x,y)])
161         else
162             if i<x then add(root1,i,a[calc(i,y)]-a[calc(i+1,y)])
163             else add(root1,i,a[calc(i,y)]-a[calc(i-1,y)]);
164     for i:=1 to m do
165         if i=y then add(root2,y,a[calc(x,y)])
166         else
167             if i<y then add(root2,i,a[calc(x,i)]-a[calc(x,i+1)])
168             else add(root2,i,a[calc(x,i)]-a[calc(x,i-1)]);
169     for i:=1 to t do
170         begin
171             read(k,x1,y1,x2,y2);
172             if k=0 then writeln(gcd(gcd(get(1,x-x1,x+x2-1,y-y1,y+y2-1),get(root1,x-x1,x+x2)),get(root2,y-y1,y+y2)))
173             else
174                 begin
175                     read(c);
176                     if (x1<=x) and (x2>=x) and (y1<=y) and (y2>=y) then
177                     begin
178                         add(root1,x,c);
179                         add(root2,y,c);
180                     end;
181                     if (x1<=x) and (x2>=x) then
182                     begin
183                         if (y1<=y) and (y1>1) then add(root2,y1-1,-c);
184                         if y1>y then add(root2,y1,c);
185                         if (y2>=y) and (y2<m) then add(root2,y2+1,-c);
186                         if y2<y then add(root2,y2,c);
187                     end;
188                     if (y1<=y) and (y2>=y) then
189                     begin
190                         if (x1<=x) and (x1>1) then add(root1,x1-1,-c);
191                         if x1>x then add(root1,x1,c);
192                         if (x2>=x) and (x2<n) then add(root1,x2+1,-c);
193                         if x2<x then add(root1,x2,c);
194                     end;
195                     add(1,x1-1,y1-1,c);
196                     add(1,x1-1,y2,-c);
197                     add(1,x2,y2,c);
198                     add(1,x2,y1-1,-c);
199                 end;
200         end;
201 end;
202  
203 begin
204     main;
205 end.
View Code

 

posted @ 2014-06-21 19:38 Randolph87 阅读(...) 评论(...) 编辑 收藏