二维平面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