Bzoj 2877 NOI2012 Magic Checkerboard Two-dimensional line segment tree

Source: Internet
Author: User

Topic: Given a matrix, two operations are supported:

1. Increment each value in a sub-matrix by one number

2. GCD of all numbers in a sub-matrix is known all ask constant over point (x, y)

Forget Bzoj No original problem I still send up the original question--



On the relationship between the length of code and the length of annotations and the ratio of the problem to simple, and the solution of Japan's drinking water resources

How the 10k+ code is refined

"GCD and correct use of modified marks"

I'm the one who set the book

"Laziness is virtue"

Cough cough.

First we can maintain a two-dimensional segment tree supporting sub-matrix modification and sub-matrix query

But we'll soon find out that this is not true because GCD (x+k,y+k)!=k+gcd (x, y)

Because the GCD is incompatible with the modified tag, our data structure cannot support interval-modified interval queries

Note the GCD (x1,x2,..., xn) =gcd (x1,x2-x1,x3-x2,..., xn-x_n-1)

If it is a one-dimensional array, we can maintain a differential, ask [X, y] to query [X+1,y] on the line segment tree gcd, and then gcd with A[x] is the answer

So we can maintain a differential matrix so we can make a single-point modification to the interval query.

The first thing I did was differential the upper-left corner.


This will maintain three line-segment trees for three regions, and ask to split the query into four pieces.

But when I finished writing the code for 8kb+ 's four line-segment tree, I found that the orange area in the diagram would not be able to avoid interval changes in any way ...

So the 8KB code ... All the waste ...

To re-read the question, we find that the point (x, y) is always in the area to ask, so we can do the difference (x, y) so that the green and orange areas are fixed, and there's no need to split.


The red squares in the figure are (x, y), we first have the difference between the center and the center, then we get the rightmost matrix.

So, since the value of e does not change, so we go straight to the line tree to find the corresponding sub-matrix GCD is the original matrix corresponding sub-matrix of the GCD

Now that's the problem with the change. We can construct the matrix with (x, Y) as the origin to divide the matrix into nine regions and then discuss the relationship between the four corners of the modified matrix four edges and the entire position and the nine regions


The red area in the figure shows +, and the green area indicates-

For a chestnut, if the upper-left corner of a matrix is in the first quadrant, it will subtract the modified value from the point (x1-1,y1)

If a matrix crosses the vertical axis and the lower boundary is below the origin, it will subtract the modified value from the point (x,y2+1)

If a matrix contains the origin point, the (x, y) point is added to the modified value

Part of the Equals argument welcome to the bottom of the code, which looks like a logical circuit.

In addition, when the first dimension of the line tree is modified, the non-leaf node cannot be changed directly to find the value of the corresponding position of two sons and merge

Finally finished ... I が life occupies, a piece of regret いなし ...

#include <vector> #include <cstdio> #include <cstring> #include <iostream> #include < Algorithm> #define M 500500using namespace Std;int m,n,q;struct array{long long memory[m];long long* operator [] (int x) {return &memory[(x-1) *n];}} A;long long GCD (long long X,long long y) {return y? GCD (y,x%y): x;} Inline long long Abs (long long x) {return x<0?-x:x;} struct Segtree{segtree *ls,*rs;long long Val; Segtree (): LS (0x0), RS (0x0), Val (0ll) {}friend void Build_tree (segtree* &p,int x,int y,long long a[]) {int mid=x+y>& Gt;1;p=new segtree;if (x==y) {P->val=a[mid];return;} Build_tree (P->ls,x,mid,a); Build_tree (p->rs,mid+1,y,a);p->val=gcd (p->ls->val,p->rs->val);//Normal segment Tree}void Modify (int x,int y, int Pos,long long val) {int mid=x+y>>1;if (x==y) {This->val+=val;return;} if (pos<=mid) ls->modify (x,mid,pos,val); else rs->modify (Mid+1,y,pos,val); THIS-&GT;VAL=GCD (ls->val,rs- >val);} Long long Get_ans (int x,int y,int l,int r) {int MID=X+Y&GT;&GT;1;if (x==l&&y==r) return val;if (R<=mid) return Ls->get_ans (X,MID,L,R); if (L>mid) return rs->get_ Ans (mid+1,y,l,r); return GCD (Ls->get_ans (X,mid,l,mid), Rs->get_ans (Mid+1,y,mid+1,r));} friend void Union (segtree* &p,segtree *p1,segtree *p2,int x,int y) {int mid=x+y>>1;if (!p) p=new segtree;if (x==y {P-&GT;VAL=GCD (p1->val,p2->val); return;} Union (P->ls,p1->ls,p2->ls,x,mid); Union (p->rs,p1->rs,p2->rs,mid+1,y);p->val=gcd (p->ls->val,p->rs->val);}; struct ABCD{ABCD *ls,*rs; Segtree *TREE;ABCD (): LS (0x0), RS (0x0), tree (0x0) {}friend void Build_tree (abcd* &p,int x,int y,array& a) {int mid= X+y>>1;p=new abcd;if (x==y) {build_tree (P->tree,1,n,a[mid]); return;} Build_tree (P->ls,x,mid,a); Build_tree (P->rs,mid+1,y,a); Union (p->tree,p->ls->tree,p->rs->tree,1,n);} void Modify (int x,int y,int pos1,int Pos2,long long val) {int mid=x+y>>1;if (x==y) {tree->modify (1,n,pos2,val); return;} if (Pos1<=mid) ls->modify (x,mid,pos1,pos2,val); else rs->modify (mid+1,y,pos1,pos2,val); Long Long Lval=ls->tree->get_ans ( 1,N,POS2,POS2); Long long Rval=rs->tree->get_ans (1,N,POS2,POS2); Long long This_val=tree->get_ans (1,n,pos2, POS2); Tree->modify (1,N,POS2,GCD (lval,rval)-this_val);} Long long Get_ans (int x,int y,int l1,int r1,int l2,int r2) {int mid=x+y>>1;if (X==L1&AMP;&AMP;Y==R1) return tree-> Get_ans (1,N,L2,R2), if (R1<=mid) return Ls->get_ans (X,MID,L1,R1,L2,R2), if (L1>mid) return Rs->get_ans (mid +1,Y,L1,R1,L2,R2); return GCD (Ls->get_ans (X,MID,L1,MID,L2,R2), Rs->get_ans (MID+1,Y,MID+1,R1,L2,R2));}} *root;int Main () {#ifndef online_judgefreopen ("2877.in", "R", stdin) freopen ("2877.out", "w", stdout), #endifint i,j,x, Y,p,x1,y1,x2,y2;long long Val;cin>>m>>n>>x>>y>>q;for (i=1;i<=m;i++) for (j=1;j< =n;j++) #ifdef online_judgescanf ("%lld", &a[i][j]), #elsescanf ("%i64d", &a[i][j]), #endiffor (i=1;i<=m;i++ ) {for (j=1;j<y;j++) a[i][j]-=a[i][j+1];for (j=n;j>y;j--) a[i][j]-=a[i][j-1];} for (j=1;j<=n;j++) {for (i=1;i<x;i++) a[i][j]-=a[i+1][j];for (i=m;i>x;i--) a[i][j]-=a[i-1][j];} Build_tree (Root,1,m,a), for (i=1;i<=q;i++) {scanf ("%d", &p), if (p==0) {scanf ("%d%d%d%d",&x1,&y1,& X2,&AMP;Y2); X1=x-x1;y1=y-y1;x2=x+x2;y2=y+y2;long long Ans=root->get_ans (1,m,x1,x2,y1,y2); Ans=Abs (ans); #ifdef online_judgeprintf ("%lld\n", ans); #elseprintf ("%i64d\n", ans); #endif}else{scanf ("%d%d%d%d",&x1,&y1,& X2,&AMP;Y2); #ifdef online_judgescanf ("%lld", &val); #elsescanf ("%i64d", &val); #endifif (X1<=x && Y1<=y && x1-1>0 && y1-1>0) root->modify (1,m,x1-1,y1-1,val); else if (x1<=x && y1& Gt;y && x1-1>0) root->modify (1,m,x1-1,y1,-val); else if (x1>x && y1<=y && y1-1>0) Root->modify (1,m,x1,y1-1,-val), else if (x1>x && y1>y) root->modify (1,m,x1,y1,val);//left Upper point (x1,y1) if (x1<=x && y2>=y && x1-1>0 &&Amp Y2+1<=n) root->modify (1,m,x1-1,y2+1,val), else if (x1<=x && y2<y && x1-1>0) root-> Modify (1,m,x1-1,y2,-val); else if (x1>x && y2>=y && y2+1<=n) root->modify (1,m,x1,y2+1,-val ), else if (x1>x && y2<y) root->modify (1,m,x1,y2,val);//Right Upper point (x1,y2) if (x2>=x && y1<=y && x2+1<=m && y1-1>0) root->modify (1,m,x2+1,y1-1,val); else if (x2<x && y1<=y && y1-1>0) root->modify (1,m,x2,y1-1,-val), else if (x2>=x && y1>y && x2+1<=m) Root->modify (1,m,x2+1,y1,-val), else if (x2<x && y1>y) root->modify (1,m,x2,y1,val);//left Lower point (x2,y1) if (x2>=x && y2>=y && x2+1<=m && y2+1<=n) root->modify (1,m,x2+1,y2+1,val); else if (x2<x && y2>=y && y2+1<=n) root->modify (1,m,x2,y2+1,-val); else if (x2>=x && y2 <y && x2+1<=m) root->modify (1,m,x2+1,y2,-val), else if (x2<x && y2<y) root->modify (1,m,x2,y2,val);//Right end point (x2,y2) if (x1<=x && x2>=x) {if (y1<=y && y1-1>0) root->modify (1,m,x,y1-1,-val); else if (y1>y) root->modify (1,m,x,y1,val);// Zoodang (x,y1) if (y2>=y && y2+1<=n) root->modify (1,m,x,y2+1,-val), else if (y2<y) root->modify (1,m,x , y2,val);//Right end point (x,y2)}if (y1<=y && y2>=y) {if (x1<=x && x1-1>0) root->modify (1,m,x1-1,y, -val), else if (x1>x) root->modify (1,m,x1,y,val);//Upper point (x1,y) if (x2>=x && x2+1<=m) root->modify ( 1,m,x2+1,y,-val), else if (x2<x) root->modify (1,m,x2,y,val);//Bottom Point (x2,y)}if (x1<=x && x2>=x & & y1<=y && y2>=y) root->modify (1,m,x,y,val);}} return 0;}


Bzoj 2877 NOI2012 Magic Checkerboard Two-dimensional line segment tree

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.