BZOJ2877:[NOI2012]魔幻棋盘
浅谈树状数组与主席树:https://www.cnblogs.com/AKMer/p/9946944.html
题目传送门:https://lydsy.com/JudgeOnline/problem.php?id=2877
这就是个屎题。
而且至今我还不知道为什么洛谷和本地都可以过但是\(BZOJ\)会\(RE\)
利用更相减损数以棋盘守护者为中心进行二维差分,那么每次修改就变成若干个点的值的修改了。
然后二维线段树维护差分值。
详细一点你们可以看这个博客(我是懒得搞了):http://www.cnblogs.com/milky-w/p/8530723.html
反正我是不想再来回头看这题了,简直屎得一批。
2019.01.03更新:递归版代码开O3可以在BZOJ过,所以我觉得是递归的锅,果然把所有递归全部改成非递归就可以过了。还是清楚为什么递归层数并不多会RE。
时间复杂度:\(O(nmlognlogm)\)
空间复杂度:\(O(mn)\)
非递归版代码如下:
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn=5e5+5;
int n,m,X,Y,T;
ll a[maxn],b[maxn];
ll read() {
ll x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
}
ll gcd(ll a,ll b) {
while(b) {
ll tmp=b;b=a%b;
a=tmp;
}
return abs(a);
}
struct tree_node {
int p,l,r;
tree_node () {}
tree_node (int _p,int _l,int _r) {
p=_p,l=_l,r=_r;
}
};
struct segment_tree_y {
int tot,top;
tree_node sta[maxn<<1];
int ls[maxn<<2],rs[maxn<<2];
ll val[maxn<<2],ans[maxn<<2];
int rt1[maxn<<1],rt2[maxn<<1];
void build(int root,int x) {
sta[++top]=tree_node(root,1,m);
int now=1;
while(now<=top) {
if(sta[now].l==sta[now].r) {now++;continue;}
int mid=(sta[now].l+sta[now].r)>>1;
ls[sta[now].p]=++tot,rs[sta[now].p]=++tot;
sta[++top]=tree_node(ls[sta[now].p],sta[now].l,mid);
sta[++top]=tree_node(rs[sta[now].p],mid+1,sta[now].r);
now++;
}
while(top) {
tree_node tmp=sta[top--];
if(tmp.l==tmp.r)val[tmp.p]=a[(x-1)*m+tmp.l];
else val[tmp.p]=gcd(val[ls[tmp.p]],val[rs[tmp.p]]);
}
}
void update(int root,int root1,int root2) {
sta[++top]=tree_node(root,1,m);
rt1[top]=root1,rt2[top]=root2;
int now=1;
while(now<=top) {
if(sta[now].l==sta[now].r) {now++;continue;}
int mid=(sta[now].l+sta[now].r)>>1;
ls[sta[now].p]=++tot,rs[sta[now].p]=++tot;
sta[++top]=tree_node(ls[sta[now].p],sta[now].l,mid);
rt1[top]=ls[rt1[now]],rt2[top]=ls[rt2[now]];
sta[++top]=tree_node(rs[sta[now].p],mid+1,sta[now].r);
rt1[top]=rs[rt1[now]],rt2[top]=rs[rt2[now]];
now++;
}
while(top) {
tree_node tmp=sta[top];
int u=rt1[top],v=rt2[top];top--;
if(tmp.l==tmp.r)val[tmp.p]=gcd(val[u],val[v]);
else val[tmp.p]=gcd(val[ls[tmp.p]],val[rs[tmp.p]]);
}
}
ll query(int rt,int L,int R) {
sta[++top]=tree_node(rt,1,m);
int now=1;
while(now<=top) {
if(L<=sta[now].l&&sta[now].r<=R) {now++;continue;}
int mid=(sta[now].l+sta[now].r)>>1;
if(L<=mid)sta[++top]=tree_node(ls[sta[now].p],sta[now].l,mid);
if(R>mid)sta[++top]=tree_node(rs[sta[now].p],mid+1,sta[now].r);
now++;
}
while(top) {
tree_node tmp=sta[top--];
if(L<=tmp.l&&tmp.r<=R)ans[tmp.p]=val[tmp.p];
else {
ans[tmp.p]=0;
int mid=(tmp.l+tmp.r)>>1;
if(L<=mid)ans[tmp.p]=ans[ls[tmp.p]];
if(R>mid)ans[tmp.p]=gcd(ans[tmp.p],ans[rs[tmp.p]]);
}
}
return ans[rt];
}
void change(int p,int pos,ll v,bool opt) {
sta[++top]=tree_node(p,1,m);
int now=1;
while(now<=top) {
if(sta[now].l==sta[now].r) {now++;continue;}
int mid=(sta[now].l+sta[now].r)>>1;
if(pos<=mid)sta[++top]=tree_node(ls[sta[now].p],sta[now].l,mid);
else sta[++top]=tree_node(rs[sta[now].p],mid+1,sta[now].r);
now++;
}
while(top) {
tree_node tmp=sta[top--];
if(tmp.l==tmp.r) {
if(opt)val[tmp.p]+=v;
else val[tmp.p]=v;
}
else val[tmp.p]=gcd(val[ls[tmp.p]],val[rs[tmp.p]]);
}
}
}T2;
struct segment_tree_x {
int top;
int rt[maxn<<2];
ll ans[maxn<<2];
tree_node sta[maxn<<1];
void build() {
sta[++top]=tree_node(1,1,n);
int now=1;
while(now<=top) {
if(sta[now].l==sta[now].r) {now++;continue;}
int mid=(sta[now].l+sta[now].r)>>1;
sta[++top]=tree_node(sta[now].p<<1,sta[now].l,mid);
sta[++top]=tree_node(sta[now].p<<1|1,mid+1,sta[now].r);
now++;
}
while(top) {
tree_node tmp=sta[top--];rt[tmp.p]=++T2.tot;
if(tmp.l==tmp.r)T2.build(rt[tmp.p],tmp.l);
else T2.update(rt[tmp.p],rt[tmp.p<<1],rt[tmp.p<<1|1]);
}
}
ll query(int x1,int x2,int y1,int y2) {
sta[++top]=tree_node(1,1,n);
int now=1;
while(now<=top) {
if(x1<=sta[now].l&&sta[now].r<=x2) {now++;continue;}
int mid=(sta[now].l+sta[now].r)>>1;
if(x1<=mid)sta[++top]=tree_node(sta[now].p<<1,sta[now].l,mid);
if(x2>mid)sta[++top]=tree_node(sta[now].p<<1|1,mid+1,sta[now].r);
now++;
}
while(top) {
tree_node tmp=sta[top--];
if(x1<=tmp.l&&tmp.r<=x2)ans[tmp.p]=T2.query(rt[tmp.p],y1,y2);
else {
ans[tmp.p]=0;int mid=(tmp.l+tmp.r)>>1;
if(x1<=mid)ans[tmp.p]=ans[tmp.p<<1];
if(x2>mid)ans[tmp.p]=gcd(ans[tmp.p],ans[tmp.p<<1|1]);
}
}
return ans[1];
}
void add(int x,int y,ll v) {
if(x<1||x>n||y<1||y>m)return;
sta[++top]=tree_node(1,1,n);
int now=1;
while(now<=top) {
if(sta[now].l==sta[now].r) {now++;continue;}
int mid=(sta[now].l+sta[now].r)>>1;
if(x<=mid)sta[++top]=tree_node(sta[now].p<<1,sta[now].l,mid);
else sta[++top]=tree_node(sta[now].p<<1|1,mid+1,sta[now].r);
now++;
}
while(top) {
tree_node tmp=sta[top--];
if(tmp.l==tmp.r)T2.change(rt[tmp.p],y,v,1);
else {
ll lv=T2.query(rt[tmp.p<<1],y,y);
ll rv=T2.query(rt[tmp.p<<1|1],y,y);
T2.change(rt[tmp.p],y,gcd(lv,rv),0);
}
}
}
}T1;
int main() {
n=read(),m=read(),X=read(),Y=read(),T=read();
for(int i=1;i<=n*m;i++)a[i]=read();
for(int i=1;i<=n*m;i++) {
int pos=(i-1)%m+1;
if(pos<Y)b[i]=a[i]-a[i+1];
else if(pos>Y)b[i]=a[i]-a[i-1];
else b[i]=a[i];
}
for(int i=1;i<=n*m;i++) {
int pos=(i-1)/m+1;
if(pos<X)a[i]=b[i]-b[i+m];
else if(pos>X)a[i]=b[i]-b[i-m];
else a[i]=b[i];
}
T1.build();
while(T--) {
int opt=read(),x1=read(),y1=read(),x2=read(),y2=read();
if(!opt) {
x1=X-x1,x2=X+x2,y1=Y-y1,y2=Y+y2;
printf("%lld\n",T1.query(x1,x2,y1,y2));
}
if(opt) {
ll val=read();
if(x1<=X&&x2>=X&&y1<=Y&&y2>=Y) {
T1.add(X,Y,val);
T1.add(x1-1,y1-1,val);
T1.add(x1-1,y2+1,val);
T1.add(x2+1,y1-1,val);
T1.add(x2+1,y2+1,val);
T1.add(x1-1,Y,-val);
T1.add(x2+1,Y,-val);
T1.add(X,y1-1,-val);
T1.add(X,y2+1,-val);
}
else if(y1<=Y&&y2>=Y) {
if(x1<X) {
T1.add(x2,Y,val);
T1.add(x1-1,y1-1,val);
T1.add(x1-1,y2+1,val);
T1.add(x1-1,Y,-val);
T1.add(x2,y1-1,-val);
T1.add(x2,y2+1,-val);
}
else {
T1.add(x1,Y,val);
T1.add(x2+1,y1-1,val);
T1.add(x2+1,y2+1,val);
T1.add(x2+1,Y,-val);
T1.add(x1,y1-1,-val);
T1.add(x1,y2+1,-val);
}
}
else if(x1<=X&&x2>=X) {
if(y1<Y) {
T1.add(X,y2,val);
T1.add(x1-1,y1-1,val);
T1.add(x2+1,y1-1,val);
T1.add(X,y1-1,-val);
T1.add(x1-1,y2,-val);
T1.add(x2+1,y2,-val);
}
else {
T1.add(X,y1,val);
T1.add(x1-1,y2+1,val);
T1.add(x2+1,y2+1,val);
T1.add(X,y2+1,-val);
T1.add(x1-1,y1,-val);
T1.add(x2+1,y1,-val);
}
}
else if(x1<X&&y1<Y) {
T1.add(x2,y2,val);
T1.add(x1-1,y1-1,val);
T1.add(x1-1,y2,-val);
T1.add(x2,y1-1,-val);
}
else if(x1<X&&y1>Y) {
T1.add(x2,y1,val);
T1.add(x1-1,y2+1,val);
T1.add(x1-1,y1,-val);
T1.add(x2,y2+1,-val);
}
else if(x1>X&&y1<Y) {
T1.add(x1,y2,val);
T1.add(x2+1,y1-1,val);
T1.add(x1,y1-1,-val);
T1.add(x2+1,y2,-val);
}
else if(x1>X&&y1>Y) {
T1.add(x1,y1,val);
T1.add(x2+1,y2+1,val);
T1.add(x1,y2+1,-val);
T1.add(x2+1,y1,-val);
}
}
}
return 0;
}
递归版代码如下:
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn=5e5+5;
int n,m,X,Y,T;
ll a[maxn],b[maxn];
ll read() {
ll x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
}
ll gcd(ll a,ll b) {
if(!b)return abs(a);
return gcd(b,a%b);
}
struct segment_tree_y {
int tot;
ll val[maxn<<2];
int ls[maxn<<2],rs[maxn<<2];
void build(int &p,int l,int r,int x) {
p=++tot;
if(l==r) {val[p]=a[(x-1)*m+l];return;}
int mid=(l+r)>>1;
build(ls[p],l,mid,x);
build(rs[p],mid+1,r,x);
val[p]=gcd(val[ls[p]],val[rs[p]]);
}
void update(int &p1,int p2,int p3,int l,int r) {
p1=++tot;
if(l==r) {val[p1]=gcd(val[p2],val[p3]);return;}
int mid=(l+r)>>1;
update(ls[p1],ls[p2],ls[p3],l,mid);
update(rs[p1],rs[p2],rs[p3],mid+1,r);
val[p1]=gcd(val[ls[p1]],val[rs[p1]]);
}
ll query(int p,int l,int r,int L,int R) {
if(L<=l&&r<=R)return val[p];
int mid=(l+r)>>1;ll res=0;
if(L<=mid)res=query(ls[p],l,mid,L,R);
if(R>mid)res=gcd(res,query(rs[p],mid+1,r,L,R));
return res;
}
void add(int p,int l,int r,int pos,ll v) {
if(l==r) {val[p]+=v;return;}
int mid=(l+r)>>1;
if(pos<=mid)add(ls[p],l,mid,pos,v);
else add(rs[p],mid+1,r,pos,v);
val[p]=gcd(val[ls[p]],val[rs[p]]);
}
void change(int p,int l,int r,int pos,ll v) {
if(l==r) {val[p]=v;return;}
int mid=(l+r)>>1;
if(pos<=mid)change(ls[p],l,mid,pos,v);
else change(rs[p],mid+1,r,pos,v);
val[p]=gcd(val[ls[p]],val[rs[p]]);
}
}T2;
struct segment_tree_x {
int rt[maxn<<2];
void build(int p,int l,int r) {
if(l==r) {T2.build(rt[p],1,m,l);return;}
int mid=(l+r)>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
T2.update(rt[p],rt[p<<1],rt[p<<1|1],1,m);
}
ll query(int p,int l,int r,int x1,int x2,int y1,int y2) {
if(x1<=l&&r<=x2)return T2.query(rt[p],1,m,y1,y2);
int mid=(l+r)>>1;ll res=0;
if(x1<=mid)res=query(p<<1,l,mid,x1,x2,y1,y2);
if(x2>mid)res=gcd(res,query(p<<1|1,mid+1,r,x1,x2,y1,y2));
return res;
}
void add(int p,int l,int r,int x,int y,ll v) {
if(x<1||x>n||y<1||y>m)return;
if(l==r) {T2.add(rt[p],1,m,y,v);return;}
int mid=(l+r)>>1;
if(x<=mid)add(p<<1,l,mid,x,y,v);
else add(p<<1|1,mid+1,r,x,y,v);
ll lv=T2.query(rt[p<<1],1,m,y,y);
ll rv=T2.query(rt[p<<1|1],1,m,y,y);
T2.change(rt[p],1,m,y,gcd(lv,rv));
}
}T1;
int main() {
n=read(),m=read(),X=read(),Y=read(),T=read();
for(int i=1;i<=n*m;i++)a[i]=read();
for(int i=1;i<=n*m;i++) {
int pos=(i-1)%m+1;
if(pos<Y)b[i]=a[i]-a[i+1];
else if(pos>Y)b[i]=a[i]-a[i-1];
else b[i]=a[i];
}
for(int i=1;i<=n*m;i++) {
int pos=(i-1)/m+1;
if(pos<X)a[i]=b[i]-b[i+m];
else if(pos>X)a[i]=b[i]-b[i-m];
else a[i]=b[i];
}
T1.build(1,1,n);
while(T--) {
int opt=read(),x1=read(),y1=read(),x2=read(),y2=read();
if(!opt) {
x1=X-x1,x2=X+x2,y1=Y-y1,y2=Y+y2;
printf("%lld\n",T1.query(1,1,n,x1,x2,y1,y2));
}
if(opt) {
ll val=read();
if(x1<=X&&x2>=X&&y1<=Y&&y2>=Y) {
T1.add(1,1,n,X,Y,val);
T1.add(1,1,n,x1-1,y1-1,val);
T1.add(1,1,n,x1-1,y2+1,val);
T1.add(1,1,n,x2+1,y1-1,val);
T1.add(1,1,n,x2+1,y2+1,val);
T1.add(1,1,n,x1-1,Y,-val);
T1.add(1,1,n,x2+1,Y,-val);
T1.add(1,1,n,X,y1-1,-val);
T1.add(1,1,n,X,y2+1,-val);
}
else if(y1<=Y&&y2>=Y) {
if(x1<X) {
T1.add(1,1,n,x2,Y,val);
T1.add(1,1,n,x1-1,y1-1,val);
T1.add(1,1,n,x1-1,y2+1,val);
T1.add(1,1,n,x1-1,Y,-val);
T1.add(1,1,n,x2,y1-1,-val);
T1.add(1,1,n,x2,y2+1,-val);
}
else {
T1.add(1,1,n,x1,Y,val);
T1.add(1,1,n,x2+1,y1-1,val);
T1.add(1,1,n,x2+1,y2+1,val);
T1.add(1,1,n,x2+1,Y,-val);
T1.add(1,1,n,x1,y1-1,-val);
T1.add(1,1,n,x1,y2+1,-val);
}
}
else if(x1<=X&&x2>=X) {
if(y1<Y) {
T1.add(1,1,n,X,y2,val);
T1.add(1,1,n,x1-1,y1-1,val);
T1.add(1,1,n,x2+1,y1-1,val);
T1.add(1,1,n,X,y1-1,-val);
T1.add(1,1,n,x1-1,y2,-val);
T1.add(1,1,n,x2+1,y2,-val);
}
else {
T1.add(1,1,n,X,y1,val);
T1.add(1,1,n,x1-1,y2+1,val);
T1.add(1,1,n,x2+1,y2+1,val);
T1.add(1,1,n,X,y2+1,-val);
T1.add(1,1,n,x1-1,y1,-val);
T1.add(1,1,n,x2+1,y1,-val);
}
}
else if(x1<X&&y1<Y) {
T1.add(1,1,n,x2,y2,val);
T1.add(1,1,n,x1-1,y1-1,val);
T1.add(1,1,n,x1-1,y2,-val);
T1.add(1,1,n,x2,y1-1,-val);
}
else if(x1<X&&y1>Y) {
T1.add(1,1,n,x2,y1,val);
T1.add(1,1,n,x1-1,y2+1,val);
T1.add(1,1,n,x1-1,y1,-val);
T1.add(1,1,n,x2,y2+1,-val);
}
else if(x1>X&&y1<Y) {
T1.add(1,1,n,x1,y2,val);
T1.add(1,1,n,x2+1,y1-1,val);
T1.add(1,1,n,x1,y1-1,-val);
T1.add(1,1,n,x2+1,y2,-val);
}
else if(x1>X&&y1>Y) {
T1.add(1,1,n,x1,y1,val);
T1.add(1,1,n,x2+1,y2+1,val);
T1.add(1,1,n,x1,y2+1,-val);
T1.add(1,1,n,x2+1,y1,-val);
}
}
}
return 0;
}