zoukankan      html  css  js  c++  java
  • hdu4819 Mosaic 二维线段树 单点更新,区间查询RMQ

    如果写二维线段树区间RMQ,不能单点更新的话,那么和咸鱼有什么区别。

    所以弄了一个下午,终于把更新弄出来了。。。

    这个是这样的,既然是单点更新,一定会更新到最底层,因此先更新到第一维的最底层,在到第二维一直更新到那个点,然后由那个点一直分两个方向更新上来。

    这样的话就不要把第二维弄成结构体了,因为要用第一维的根值,不过这样反而更好写。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define MS0(a) memset(a,0,sizeof(a))
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    
    using namespace std;
    
    typedef long long ll;
    const int maxn=1200;
    const int INF=1e9+10;
    
    int n,q;
    int x,y,z;
    int t,A,B;
    struct Node
    {
        int Min,Max;
    };Node tr[maxn<<2][maxn<<2];
    
    void upy(int rt,int rtx)
    {
        tr[rtx][rt].Min=min(tr[rtx][rt<<1].Min,tr[rtx][rt<<1|1].Min);
        tr[rtx][rt].Max=max(tr[rtx][rt<<1].Max,tr[rtx][rt<<1|1].Max);
    }
    
    void buildy(int l,int r,int rt,int rtx)
    {
        if(l==r){
            tr[rtx][rt].Max=-INF;
            tr[rtx][rt].Min=INF;
            return;
        }
        int m=(l+r)>>1;
        buildy(lson,rtx);
        buildy(rson,rtx);
        upy(rt,rtx);
    }
    
    void updatey(int p,int c,int l,int r,int rt,int rtx)
    {
        if(l==r){
            tr[rtx][rt].Min=tr[rtx][rt].Max=c;
            return;
        }
        int m=(l+r)>>1;
        if(p<=m) updatey(p,c,lson,rtx);
        else updatey(p,c,rson,rtx);
        upy(rt,rtx);
    }
    
    int queryMiny(int L,int R,int l,int r,int rt,int rtx)
    {
        if(L<=l&&r<=R) return tr[rtx][rt].Min;
        int m=(l+r)>>1;
        int res=INF;
        if(L<=m) res=min(res,queryMiny(L,R,lson,rtx));
        if(R>m) res=min(res,queryMiny(L,R,rson,rtx));
        return res;
    }
    
    int queryMaxy(int L,int R,int l,int r,int rt,int rtx)
    {
        if(L<=l&&r<=R) return tr[rtx][rt].Max;
        int m=(l+r)>>1;
        int res=-INF;
        if(L<=m) res=max(res,queryMaxy(L,R,lson,rtx));
        if(R>m) res=max(res,queryMaxy(L,R,rson,rtx));
        return res;
    }
    
    void buildx(int l,int r,int rt)
    {
        buildy(1,n,1,rt);
        if(l==r) return;
        int m=(l+r)>>1;
        buildx(lson);
        buildx(rson);
    }
    
    void upx(int p,int rtx,int l,int r,int rt)
    {
        tr[rtx][rt].Min=min(tr[rtx<<1][rt].Min,tr[rtx<<1|1][rt].Min);
        tr[rtx][rt].Max=max(tr[rtx<<1][rt].Max,tr[rtx<<1|1][rt].Max);
        if(l==r) return;
        int m=(l+r)>>1;
        if(p<=m) upx(p,rtx,lson);
        else upx(p,rtx,rson);
    }
    
    void updatex(int x,int y,int c,int l,int r,int rt)
    {
        if(l==r){
            updatey(y,c,1,n,1,rt);
            return;
        }
        int m=(l+r)>>1;
        if(x<=m) updatex(x,y,c,lson);
        else updatex(x,y,c,rson);
        upx(y,rt,1,n,1);
    }
    
    int queryMinx(int xL,int xR,int yL,int yR,int l,int r,int rt)
    {
        if(xL<=l&&r<=xR) return queryMiny(yL,yR,1,n,1,rt);
        int m=(l+r)>>1;
        int res=INF;
        if(xL<=m) res=min(res,queryMinx(xL,xR,yL,yR,lson));
        if(xR>m) res=min(res,queryMinx(xL,xR,yL,yR,rson));
        return res;
    }
    
    int queryMaxx(int xL,int xR,int yL,int yR,int l,int r,int rt)
    {
        if(xL<=l&&r<=xR) return queryMaxy(yL,yR,1,n,1,rt);
        int m=(l+r)>>1;
        int res=-INF;
        if(xL<=m) res=max(res,queryMaxx(xL,xR,yL,yR,lson));
        if(xR>m) res=max(res,queryMaxx(xL,xR,yL,yR,rson));
        return res;
    }
    
    int main()
    {
        freopen("in.txt","r",stdin);
        int T;cin>>T;
        int casen=1;
        while(T--){
            scanf("%d",&n);
            buildx(1,n,1);
            REP(i,1,n) REP(j,1,n) scanf("%d",&x),updatex(i,j,x,1,n,1);
            scanf("%d",&q);
            printf("Case #%d:
    ",casen++);
            while(q--){
                scanf("%d%d%d",&x,&y,&z);
                t=(z-1)/2;
                A=queryMinx(x-t,x+t,y-t,y+t,1,n,1);
                B=queryMaxx(x-t,x+t,y-t,y+t,1,n,1);
                updatex(x,y,(A+B)/2,1,n,1);
                printf("%d
    ",(A+B)/2);
            }
        }
        return 0;
    }
    View Code

    这样其实不管是区间求和,区间最值,或者区间合并,只要只涉及单点更新不涉及区间更新的,基本没什么难度。

    问题在于如何处理更一般区间更新然后区间查询的。

    如果是区间更新,单点查询的话,这样只要用一些性质,不把标记传递下去,查询的时候直接路过路径上的结点的时候通过标记顺便更新,这是一个很好用的做法,它有个专业名词叫标记永久化,但不能改变它奇技淫巧的本质。。。

    其实先上面第一种做法,设个两个标记感觉还是可以传递的,反正从修改的地方一直分两个方向更新上来,不过写起来感觉略复杂啊。。。以后再弄。。。

    现在的重点不是二维线段树,而是树套树。。。

    没有AC不了的题,只有不努力的ACMER!
  • 相关阅读:
    xshell+xftp破解版下载安装以及使用教程
    XFTP安装和Xshell配置
    spark-shell的Scala的一些方法详解
    Xshell连接Linux系统
    虚拟机的使用克隆及网络配置
    dochub批量上传教程
    可汗儿童版kids安卓版下载安装教程
    2020年MySQL数据库面试题总结(50道题含答案解析)
    什么是a站、b站、c站、d站、e站、f站、g站、h站、i站、j站、k站、l站、m站、n站…z站?
    ApacheCN JavaWeb 译文集 20211017 更新
  • 原文地址:https://www.cnblogs.com/--560/p/5245481.html
Copyright © 2011-2022 走看看