二维平面RMQ问题,单点修改,区间询问最大最小值
树套树或者四叉树均可做
树套树版本:
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=500+10,mod=1e9+7,inf=0x3f3f3f3f; 5 int n,Q,a[N][N]; 6 struct D {int mx,mi;} tr[N<<2][N<<2]; 7 D operator+(const D& a,const D& b) {return {max(a.mx,b.mx),min(a.mi,b.mi)};} 8 #define ls(u) (u<<1) 9 #define rs(u) (u<<1|1) 10 #define mid ((l+r)>>1) 11 void pu(int U,int u) {tr[U][u]=tr[U][ls(u)]+tr[U][rs(u)];} 12 D qry2(int U,int y1,int y2,int u=1,int l=1,int r=n) { 13 if(l>=y1&&r<=y2)return tr[U][u]; 14 if(l>y2||r<y1)return {~inf,inf}; 15 return qry2(U,y1,y2,ls(u),l,mid)+qry2(U,y1,y2,rs(u),mid+1,r); 16 } 17 D qry(int x1,int y1,int x2,int y2,int u=1,int l=1,int r=n) { 18 if(l>=x1&&r<=x2)return qry2(u,y1,y2); 19 if(l>x2||r<x1)return {~inf,inf}; 20 return qry(x1,y1,x2,y2,ls(u),l,mid)+qry(x1,y1,x2,y2,rs(u),mid+1,r); 21 } 22 void upd2(int U,int L,int R,int y,int v,int u=1,int l=1,int r=n) { 23 if(l==r) { 24 if(L==R)tr[U][u]= {v,v}; 25 else tr[U][u]=tr[ls(U)][u]+tr[rs(U)][u]; 26 return; 27 } 28 y<=mid?upd2(U,L,R,y,v,ls(u),l,mid):upd2(U,L,R,y,v,rs(u),mid+1,r); 29 pu(U,u); 30 } 31 void upd(int x,int y,int v,int u=1,int l=1,int r=n) { 32 if(l<r)x<=mid?upd(x,y,v,ls(u),l,mid):upd(x,y,v,rs(u),mid+1,r); 33 upd2(u,l,r,y,v); 34 } 35 void build2(int U,int L,int R,int u=1,int l=1,int r=n) { 36 if(l==r) { 37 if(L==R)tr[U][u]= {a[L][l],a[L][l]}; 38 else tr[U][u]=tr[ls(U)][u]+tr[rs(U)][u]; 39 return; 40 } 41 build2(U,L,R,ls(u),l,mid),build2(U,L,R,rs(u),mid+1,r),pu(U,u); 42 } 43 void build(int u=1,int l=1,int r=n) { 44 if(l<r)build(ls(u),l,mid),build(rs(u),mid+1,r); 45 build2(u,l,r); 46 } 47 int main() { 48 scanf("%d",&n); 49 for(int i=1; i<=n; ++i) 50 for(int j=1; j<=n; ++j)scanf("%d",&a[i][j]); 51 build(); 52 for(scanf("%d",&Q); Q--;) { 53 char ch; 54 int x1,y1,x2,y2,v; 55 scanf(" %c",&ch); 56 if(ch=='q') { 57 scanf("%d%d%d%d",&x1,&y1,&x2,&y2); 58 D t=qry(x1,y1,x2,y2); 59 printf("%d %d\n",t.mx,t.mi); 60 } else { 61 scanf("%d%d%d",&x1,&y1,&v); 62 upd(x1,y1,v); 63 } 64 } 65 return 0; 66 }
四叉树版本:(ps:这个四叉树是我yy出来的,网上能找到的资料很少,我也不知道写的对不对。和树套树相比好像能避免冗余区间?虽然速度慢了些(常数问题?))
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=500+10,mod=1e9+7,inf=0x3f3f3f3f; 5 int n,Q,a[N][N]; 6 struct D {int mx,mi;} tr[(N*N)<<2]; 7 D operator+(const D& a,const D& b) {return {max(a.mx,b.mx),min(a.mi,b.mi)};} 8 #define lu (u<<2) 9 #define ru (u<<2|1) 10 #define ld (u<<2|2) 11 #define rd (u<<2|3) 12 #define xmid ((x1+x2)>>1) 13 #define ymid ((y1+y2)>>1) 14 void pu(int u,int x1,int x2,int y1,int y2) { 15 tr[u]=tr[lu]; 16 if(y1<y2)tr[u]=tr[u]+tr[ru]; 17 if(x1<x2)tr[u]=tr[u]+tr[ld]; 18 if(x1<x2&&y1<y2)tr[u]=tr[u]+tr[rd]; 19 } 20 D qry(int X1,int Y1,int X2,int Y2,int u=1,int x1=1,int x2=n,int y1=1,int y2=n) { 21 if(x1>=X1&&x2<=X2&&y1>=Y1&&y2<=Y2)return tr[u]; 22 if(x1>X2||x2<X1||y1>Y2||y2<Y1)return {~inf,inf}; 23 D ret=qry(X1,Y1,X2,Y2,lu,x1,xmid,y1,ymid); 24 if(y1<y2)ret=ret+qry(X1,Y1,X2,Y2,ru,x1,xmid,ymid+1,y2); 25 if(x1<x2)ret=ret+qry(X1,Y1,X2,Y2,ld,xmid+1,x2,y1,ymid); 26 if(x1<x2&&y1<y2)ret=ret+qry(X1,Y1,X2,Y2,rd,xmid+1,x2,ymid+1,y2); 27 return ret; 28 } 29 void upd(int X,int Y,int v,int u=1,int x1=1,int x2=n,int y1=1,int y2=n) { 30 if(x1==x2&&y1==y2) {tr[u]= {v,v}; return;} 31 if(X<=xmid&&Y<=ymid)upd(X,Y,v,lu,x1,xmid,y1,ymid); 32 else if(X<=xmid)upd(X,Y,v,ru,x1,xmid,ymid+1,y2); 33 else if(Y<=ymid)upd(X,Y,v,ld,xmid+1,x2,y1,ymid); 34 else upd(X,Y,v,rd,xmid+1,x2,ymid+1,y2); 35 pu(u,x1,x2,y1,y2); 36 } 37 void build(int u=1,int x1=1,int x2=n,int y1=1,int y2=n) { 38 if(x1==x2&&y1==y2) {tr[u]= {a[x1][y1],a[x1][y1]}; return;} 39 build(lu,x1,xmid,y1,ymid); 40 if(y1<y2)build(ru,x1,xmid,ymid+1,y2); 41 if(x1<x2)build(ld,xmid+1,x2,y1,ymid); 42 if(x1<x2&&y1<y2)build(rd,xmid+1,x2,ymid+1,y2); 43 pu(u,x1,x2,y1,y2); 44 } 45 int main() { 46 scanf("%d",&n); 47 for(int i=1; i<=n; ++i) 48 for(int j=1; j<=n; ++j)scanf("%d",&a[i][j]); 49 build(); 50 for(scanf("%d",&Q); Q--;) { 51 char ch; 52 int x1,y1,x2,y2,v; 53 scanf(" %c",&ch); 54 if(ch=='q') { 55 scanf("%d%d%d%d",&x1,&y1,&x2,&y2); 56 D t=qry(x1,y1,x2,y2); 57 printf("%d %d\n",t.mx,t.mi); 58 } else { 59 scanf("%d%d%d",&x1,&y1,&v); 60 upd(x1,y1,v); 61 } 62 } 63 return 0; 64 }
来源:https://www.cnblogs.com/asdfsag/p/12391812.html