zoukankan      html  css  js  c++  java
  • UVA

    题目链接

    二维平面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
    ",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)<<3];
     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
    ",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 }
  • 相关阅读:
    C#学习五
    C#学习二
    C#学习五
    完成车牌识别,自行拍车牌图片进行上传并查看结果
    C#学习
    简述ASP.NET网站开发步骤
    C#学习四
    C#学习三
    完成身份证识别,自行拍摄身份证图片进行上传并查看结果
    C#学习总结
  • 原文地址:https://www.cnblogs.com/asdfsag/p/12391812.html
Copyright © 2011-2022 走看看