UVA - 11297 Census (树套树/四叉树)

人走茶凉 提交于 2020-03-01 21:09:27

题目链接

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

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!