标签:
http://www.lydsy.com/JudgeOnline/problem.php?id=2877
二维线段树。
好恶。。。。。。
B类数据:
棋盘是一维的。
我们有一个结论:
$gcd(a_{1},a_{2},...,a_{n-1},a_{n})=gcd(a_{2}-a_{1},a_{3}-a_{2},...,a_{n}-a_{n-1},a_{1})$
证明:
假设集合A是a1,a2,...,an-1,an的所有公约数的集合,集合B是a2-a1,a3-a2,...,an-an-1,a1的所有公约数的集合。
对于所有的r∈A,r|a1,r|a2,...,r|an-1,r|an。
其必满足r|a2-a1,r|a3-a2,...,r|an-an-1,r|a1。
所以A⊆B。
对于所有的r∈B,r|a1,r|a2-a1,r|a3-a2,...,r|an-an-1。
其必满足:
∵r|a1,r|a2-a1
∴r|{a1-(a2-a1)} ==> r|-a2 ==> r|a2
∵r|a2,r|a3-a2
∴r|{a2-(a3-a2)} ==> r|-a3 ==> r|a3
......
∵r|an-1,r|an-an-1
∴r|{an-1 - (an - an-1)} ==> r|-an ==> r|an
所以B⊆A。
故A=B。
所以:
$gcd(a_{1},a_{2},...,a_{n-1},a_{n})=gcd(a_{2}-a_{1},a_{3}-a_{2},...,a_{n}-a_{n-1},a_{1})$
我们记b[i]=a[i]-a[i-1]。
假设询问[l,R]中的最大公约数,其实就是求gcd(a[L],gcd(b[L+1]...b[R]))。
如果将[l,R]中数都加上C,其实就是a[L...R]加上C,b[L]加上C,b[R+1]减去C。
这可以用2棵线段树维护。
C类数据:
棋盘是二维的。
我们可以从一维推广一下。
原本是这样的:
$a_{4,1},a_{4,2},a_{4,3},a_{4,4}$
$a_{3,1},a_{3,2},a_{3,3},a_{3,4}$
$a_{2,1},a_{2,2},a_{2,3},a_{2,4}$
$a_{1,1},a_{1,2},a_{1,3},a_{1,4}$
右减左:
$a_{4,1},a_{4,2}-a_{4,1},a_{4,3}-a_{4,2},a_{4,4}-a_{4,3}$
$a_{3,1},a_{3,2}-a_{3,1},a_{3,3}-a_{3,2},a_{3,4}-a_{3,3}$
$a_{2,1},a_{2,2}-a_{2,1},a_{2,3}-a_{2,2},a_{2,4}-a_{2,3}$
$a_{1,1},a_{1,2}-a_{1,1},a_{1,3}-a_{1,2},a_{1,4}-a_{1,3}$
上减下:
$a_{4,1}-a_{3,1},a_{4,2}-a_{4,1}-a_{3,2}+a_{3,1},a_{4,3}-a_{4,2}-a_{3,3}+a_{3,2},a_{4,4}-a_{4,3}-a_{3,4}+a_{3,3}$
$a_{3,1}-a_{2,1},a_{3,2}-a_{3,1}-a_{2,2}+a_{2,1},a_{3,3}-a_{3,2}-a_{2,3}+a_{2,2},a_{3,4}-a_{3,3}-a_{2,4}+a_{2,3}$
$a_{2,1}-a_{1,1},a_{2,2}-a_{2,1}-a_{1,2}+a_{1,1},a_{2,3}-a_{2,2}-a_{1,3}+a_{1,2},a_{2,4}-a_{2,3}-a_{1,4}+a_{1,3}$
$a_{1,1} , a_{1,2}-a_{1,1}, a_{1,3}-a_{1,2}, a_{1,4}-a_{1,3}$
其实就是变成了b[i][j]=a[i][j]-a[i-1][j]-a[i][j-1]+a[i-1][j-1]
我们在原图中以(X,Y)为原点建立平面直角坐标系,将棋盘分成四部分,每个部分的操作时一样的。
1:
以(x1,y1)为左下角,(x2,y2)为右上角的矩形区域都加C。
我们发现只有(x1,y1),(x1,y2+1),(x2+1,y1),(x2+1,y2+1)发生了改变。
单点修改,可以用二维线段树。
注意在第一维线段树中,对于非叶子节点,我们更新的时候要要从子节点中得到更新。
2:
求以(1,1)为左下角,(x,y)为右上角的矩形区间的gcd。
直接在二维线段树中询问。
#include<cstdio> #include<cstdlib> #include<iostream> #include<fstream> #include<algorithm> #include<cstring> #include<string> #include<cmath> #include<queue> #include<stack> #include<map> #include<utility> #include<set> #include<bitset> #include<vector> #include<functional> #include<deque> #include<cctype> #include<climits> #include<complex> //#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj using namespace std; typedef long long LL; typedef double DB; typedef pair<int,int> PII; typedef complex<DB> CP; #define mmst(a,v) memset(a,v,sizeof(a)) #define mmcy(a,b) memcpy(a,b,sizeof(a)) #define re(i,a,b) for(i=a;i<=b;i++) #define red(i,a,b) for(i=a;i>=b;i--) #define fi first #define se second #define m_p(a,b) make_pair(a,b) #define SF scanf #define PF printf #define two(k) (1<<(k)) template<class T>inline T sqr(T x){return x*x;} template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;} template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;} const DB EPS=1e-9; inline int sgn(DB x){if(abs(x)<EPS)return 0;return(x>0)?1:-1;} const DB Pi=acos(-1.0); inline int gint() { int res=0;bool neg=0;char z; for(z=getchar();z!=EOF && z!=‘-‘ && !isdigit(z);z=getchar()); if(z==EOF)return 0; if(z==‘-‘){neg=1;z=getchar();} for(;z!=EOF && isdigit(z);res=res*10+z-‘0‘,z=getchar()); return (neg)?-res:res; } inline LL gll() { LL res=0;bool neg=0;char z; for(z=getchar();z!=EOF && z!=‘-‘ && !isdigit(z);z=getchar()); if(z==EOF)return 0; if(z==‘-‘){neg=1;z=getchar();} for(;z!=EOF && isdigit(z);res=res*10+z-‘0‘,z=getchar()); return (neg)?-res:res; } const int maxN=500000; int N,M,X,Y,T; vector<LL> mp[maxN+1000]; inline LL gcd(LL a,LL b){LL ta,tb;if(a<0) a=-a;if(b<0) b=-b;for(;b!=0;ta=b,tb=a%b,a=ta,b=tb);return a;} struct Tnode { Tnode *l,*r;LL v; inline Tnode(){l=r=0;v=0;} inline LL lv(){return l?l->v:0;} inline LL rv(){return r?r->v:0;} }; Tnode mem[10000000]; int MID=-1; inline Tnode *New_Node(){mem[++MID]=Tnode();return mem+MID;} struct Tdata { int N,M; Tnode *root[4*maxN+1000]; inline void clear(int _N,int _M){N=_N;M=_M;} inline void update1(Tnode *&rt,int l,int r,int x,LL C) { if(l>r || x<l || r<x) return; if(!rt) rt=New_Node(); if(x<=l && r<=x){rt->v+=C;return;} int mid=(l+r)/2; if(x<=mid) update1(rt->l,l,mid,x,C); else update1(rt->r,mid+1,r,x,C); rt->v=gcd(rt->lv(),rt->rv()); } inline void update2(Tnode *&rt,Tnode *&rtl,Tnode *&rtr,int l,int r,int x) { if(l>r || x<l || r<x) return; if(!rt) rt=New_Node(); if(!rtl) rtl=New_Node(); if(!rtr) rtr=New_Node(); if(x<=l && r<=x){rt->v=gcd( rtl->v ,rtr->v ); return;} int mid=(l+r)/2; if(x<=mid)update2(rt->l,rtl->l,rtr->l,l,mid,x);else update2(rt->r,rtl->r,rtr->r,mid+1,r,x); rt->v=gcd(rt->lv(),rt->rv()); } inline LL ask(Tnode *&rt,int l,int r,int x,int y) { if(l>r || x>y || r<x || y<l) return 0; if(!rt) return 0; if(x<=l && r<=y) return rt->v; int mid=(l+r)/2; return gcd( ask(rt->l,l,mid,x,y) , ask(rt->r,mid+1,r,x,y) ); } inline LL ask(int rt,int l,int r,int x1,int y1,int x2,int y2) { if(l>r || x1>x2 || x2<l || r<x1) return 0; if(x1<=l && r<=x2) return ask(root[rt],1,M,y1,y2); int mid=(l+r)/2; return gcd( ask(rt*2,l,mid,x1,y1,x2,y2) , ask(rt*2+1,mid+1,r,x1,y1,x2,y2) ); } inline void update(int rt,int l,int r,int x,int y,LL C) { if(l>r || x<l || r<x)return; int mid=(l+r)/2; if(l==r) update1(root[rt],1,M,y,C); else { if(x<=mid)update(rt*2,l,mid,x,y,C); else update(rt*2+1,mid+1,r,x,y,C); update2(root[rt],root[rt*2],root[rt*2+1],1,M,y); } } inline LL xunwen(int x,int y) { return ask(1,1,N,1,1,x,y); } inline void xiugai(PII t1,PII t2,LL C) { int x1=t1.fi,y1=t1.se,x2=t2.fi,y2=t2.se; if(x1>x2)swap(x1,x2); if(y1>y2)swap(y1,y2); update(1,1,N,x1,y1,C); if(x2+1<=N)update(1,1,N,x2+1,y1,-C); if(y2+1<=M)update(1,1,N,x1,y2+1,-C); if(x2+1<=N && y2+1<=M)update(1,1,N,x2+1,y2+1,C); } }data[4]; inline PII zhuan(int f,int i,int j) { switch(f) { case 0:return PII(j-Y+1,X-i+1);break; case 1:return PII(Y-j+1,X-i+1);break; case 2:return PII(Y-j+1,i-X+1);break; case 3:return PII(j-Y+1,i-X+1);break; } } inline void build() { int i,j; data[0].clear(M-Y+1,X); re(i,1,X)re(j,Y,M)data[0].xiugai(zhuan(0,i,j),zhuan(0,i,j),mp[i][j]); data[1].clear(Y,X); re(i,1,X)re(j,1,Y)data[1].xiugai(zhuan(1,i,j),zhuan(1,i,j),mp[i][j]); data[2].clear(Y,N-X+1); re(i,X,N)re(j,1,Y)data[2].xiugai(zhuan(2,i,j),zhuan(2,i,j),mp[i][j]); data[3].clear(M-Y+1,N-X+1); re(i,X,N)re(j,Y,M)data[3].xiugai(zhuan(3,i,j),zhuan(3,i,j),mp[i][j]); } int main() { freopen("chess.in","r",stdin); freopen("chess.out","w",stdout); int i,j; N=gint();M=gint(); X=gint();Y=gint(); T=gint(); re(i,1,N){mp[i].push_back(0);re(j,1,M)mp[i].push_back(gll());mp[i].push_back(0);} re(j,0,M+1)mp[0].push_back(0),mp[N+1].push_back(0); build(); while(T--) { int f=gint(),x1=gint(),y1=gint(),x2=gint(),y2=gint(); LL C,res; switch(f) { case 0: res=0; res=gcd(res,data[0].xunwen(y2+1,x1+1)); res=gcd(res,data[1].xunwen(y1+1,x1+1)); res=gcd(res,data[2].xunwen(y1+1,x2+1)); res=gcd(res,data[3].xunwen(y2+1,x2+1)); PF("%I64d\n",res); break; case 1: C=gll(); if(x1<=X && y2>=Y) data[0].xiugai( zhuan(0,min(X,x2),max(Y,y1)) , zhuan(0,x1,y2) , C ); if(x1<=X && y1<=Y) data[1].xiugai( zhuan(1,min(X,x2),min(Y,y2)) , zhuan(1,x1,y1) , C ); if(x2>=X && y1<=Y) data[2].xiugai( zhuan(2,max(X,x1),min(Y,y2)) , zhuan(2,x2,y1) , C ); if(x2>=X && y2>=Y) data[3].xiugai( zhuan(3,max(X,x1),max(Y,y1)) , zhuan(3,x2,y2) , C ); break; } } return 0; }
标签:
原文地址:http://www.cnblogs.com/maijing/p/4693715.html