2877: [Noi2012]魔幻棋盘 - BZOJ
2014-06-21 19:38
183 查看
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个矩形拼在一起就变成了正解里的那个奇怪的矩阵
第一次打二维线段树
View Code
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个矩形拼在一起就变成了正解里的那个奇怪的矩阵
第一次打二维线段树
const maxn=500000; type node=record l,r,lc,rc:longint; a:int64; end; var a,b:array[0..maxn]of int64; f,f2:array[0..maxn*4]of node; n,m,t,x,y,tot,cnt,ll,rr,root1,root2:longint; function calc(a,b:longint):longint; begin exit((a-1)*m+b); end; function gcd(a,b:int64):int64; begin if b=0 then exit(a); exit(gcd(b,a mod b)); end; procedure new(x,y,z:longint); begin f2[x].a:=gcd(abs(f2[y].a),abs(f2[z].a)); if f2[x].l=f2[x].r then exit; new(f2[x].lc,f2[y].lc,f2[z].lc); new(f2[x].rc,f2[y].rc,f2[z].rc); end; procedure build2(l,r:longint); var now,mid:longint; begin if l>r then exit; inc(cnt);now:=cnt; f2[now].l:=l;f2[now].r:=r; if l=r then begin if ll=rr then f2[now].a:=b[calc(ll,l)]; exit; end; mid:=(l+r)>>1; f2[now].lc:=cnt+1; build2(l,mid); f2[now].rc:=cnt+1; build2(mid+1,r); if ll=rr then f2[now].a:=gcd(abs(f2[f2[now].lc].a),abs(f2[f2[now].rc].a)); end; procedure build(l,r:longint); var now,mid:longint; begin if l>r then exit; inc(tot);now:=tot; f[now].l:=l;f[now].r:=r; if l=r then begin f[now].a:=cnt+1; ll:=l;rr:=r; build2(1,m-1); exit; end; mid:=(l+r)>>1; f[now].lc:=tot+1; build(l,mid); f[now].rc:=tot+1; build(mid+1,r); f[now].a:=cnt+1; ll:=l;rr:=r; build2(1,m-1); new(f[now].a,f[f[now].lc].a,f[f[now].rc].a); end; function get(now,l,r:longint):int64; var mid:longint; begin if (f2[now].l>=l) and (f2[now].r<=r) then exit(abs(f2[now].a)); mid:=(f2[now].l+f2[now].r)>>1; get:=0; if l<=mid then get:=gcd(get(f2[now].lc,l,r),get); if r>mid then get:=gcd(get(f2[now].rc,l,r),get); end; function get(now,x1,y1,x2,y2:longint):int64; var mid:longint; begin if (x1>y1) or (x2>y2) then exit(0); if (f[now].l>=x1) and (f[now].r<=y1) then exit(get(f[now].a,x2,y2)); get:=0;mid:=(f[now].l+f[now].r)>>1; if x1<=mid then get:=gcd(get(f[now].lc,x1,y1,x2,y2),get); if y1>mid then get:=gcd(get(f[now].rc,x1,y1,x2,y2),get); end; procedure new(x,y,z,k:longint); var mid:longint; begin f2[x].a:=gcd(abs(f2[y].a),abs(f2[z].a)); if f2[x].l=f2[x].r then exit; mid:=(f2[x].l+f2[x].r)>>1; if k<=mid then new(f2[x].lc,f2[y].lc,f2[z].lc,k) else new(f2[x].rc,f2[y].rc,f2[z].rc,k); end; procedure add(now,x:longint;c:int64); var mid:longint; begin if f2[now].l=f2[now].r then begin inc(f2[now].a,c); exit; end; mid:=(f2[now].l+f2[now].r)>>1; if x<=mid then add(f2[now].lc,x,c) else add(f2[now].rc,x,c); f2[now].a:=gcd(abs(f2[f2[now].lc].a),abs(f2[f2[now].rc].a)); end; procedure add(now,x,y:longint;c:int64); var mid:longint; begin if (x<1) or (x>=n) or (y<1) or (y>=m) then exit; if f[now].l=f[now].r then begin add(f[now].a,y,c); exit; end; mid:=(f[now].l+f[now].r)>>1; if x<=mid then add(f[now].lc,x,y,c) else add(f[now].rc,x,y,c); new(f[now].a,f[f[now].lc].a,f[f[now].rc].a,y); end; procedure main; var i,j,k,x1,y1,x2,y2:longint; c:int64; begin read(n,m,x,y,t); for i:=1 to n do for j:=1 to m do read(a[calc(i,j)]); for i:=1 to n-1 do for j:=1 to m-1 do b[calc(i,j)]:=a[calc(i,j)]+a[calc(i+1,j+1)]-a[calc(i,j+1)]-a[calc(i+1,j)]; build(1,n-1); ll:=rr+1; root1:=cnt+1; build2(1,n); root2:=cnt+1; build2(1,m); for i:=1 to n do if i=x then add(root1,x,a[calc(x,y)]) else if i<x then add(root1,i,a[calc(i,y)]-a[calc(i+1,y)]) else add(root1,i,a[calc(i,y)]-a[calc(i-1,y)]); for i:=1 to m do if i=y then add(root2,y,a[calc(x,y)]) else if i<y then add(root2,i,a[calc(x,i)]-a[calc(x,i+1)]) else add(root2,i,a[calc(x,i)]-a[calc(x,i-1)]); for i:=1 to t do begin read(k,x1,y1,x2,y2); 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))) else begin read(c); if (x1<=x) and (x2>=x) and (y1<=y) and (y2>=y) then begin add(root1,x,c); add(root2,y,c); end; if (x1<=x) and (x2>=x) then begin if (y1<=y) and (y1>1) then add(root2,y1-1,-c); if y1>y then add(root2,y1,c); if (y2>=y) and (y2<m) then add(root2,y2+1,-c); if y2<y then add(root2,y2,c); end; if (y1<=y) and (y2>=y) then begin if (x1<=x) and (x1>1) then add(root1,x1-1,-c); if x1>x then add(root1,x1,c); if (x2>=x) and (x2<n) then add(root1,x2+1,-c); if x2<x then add(root1,x2,c); end; add(1,x1-1,y1-1,c); add(1,x1-1,y2,-c); add(1,x2,y2,c); add(1,x2,y1-1,-c); end; end; end; begin main; end.
View Code
相关文章推荐
- BZOJ 2877 NOI2012 魔幻棋盘 二维线段树
- bzoj2877 [Noi2012]魔幻棋盘 二维线段树
- [BZOJ2877][Noi2012]魔幻棋盘 && 二维线段树+差分
- BZOJ2877 [Noi2012]魔幻棋盘
- bzoj 2877: [Noi2012]魔幻棋盘
- bzoj2877 [Noi2012]魔幻棋盘 [二维线段树]
- 【bzoj2877】 Noi2012—魔幻棋盘
- BZOJ 2875 2875: [NOI2012]随机数生成器
- [BZOJ2879][Noi2012]美食节(最小费用最大流动态加边)
- BZOJ 2879 NOI2012美食节
- BZOJ 2879: [Noi2012]美食节 费用流 动态加边
- 【bzoj2875】 Noi2012—随机数生成器
- [BZOJ 2875][NOI 2012]随机数生成器(矩阵快速幂)
- 【BZOJ】2875: [Noi2012]随机数生成器(矩阵乘法+快速乘)
- BZOJ 2879 [Noi2012]美食节 | 费用流 动态开点
- bzoj2875 [noi2012]随机数生成器(矩阵倍增)
- BZOJ 2879 NOI2012 美食节 费用流
- BZOJ2878 [Noi2012]迷失游乐园 【基环树 + 树形dp + 期望dp】
- 【BZOJ】2876: [Noi2012]骑行川藏
- BZOJ2875: [Noi2012]随机数生成器 矩阵乘法+快速乘