• 【线段树】牛客 Practice for KD Tree (二维线段树/树套树)


    Practice for KD Tree

    题意:

    一个 (n*n) 矩阵 (A) ,有 (m_1) 个操作:给 (x_1;x_2;y_1;y_2;w) ,对所有(A_{ij}) ((iin[x_1,x_2])(jin[y_1,y_2]) )加上 (w)
    (m_2) 个询问:给 (x_1;x_2;y_1;y_2) ,求出(A_{ij}) ((iin[x_1,x_2])(jin[y_1,y_2]) )的最大值。

    输入:

    (1)(3) 个整数 (n;m_1;m_2)(1≤n≤2000,1≤m_1≤5*10^4,1≤m_2≤5*10^5) );
    之后 (m_1) 行,每行 (5) 个整数:(x_1;x_2;y_1;y_2;w)(1≤x_1≤x_2≤n,1≤y_1≤y_2≤n,1≤w≤10^9) );
    之后 (m_2) 行,每行 (4) 个整数:(x_1;x_2;y_1;y_2)(1≤x_1≤x_2≤n,1≤y_1≤y_2≤n) );

    输出:

    输出m2行,每行一个整数

    官方题解:

    n小,所以可以用 (O(n^2))计算出矩阵。然后可以用二维线段树求最值。


    个人积累:

    【一开始用树状数组求矩阵,明明都是二维差分的思路,我却没想到用二维差分直接 (O(n^2)) 求矩阵....
    【练习不足o(︶︿︶)o
    【然后因为这个树状数组建了四个 (c[maxn][maxn]) (MLE) ,原本以为线段树 (tr[maxn<<2][maxn<<2]) 才可能 (MLE) 来着。。结果并不


    因为是确定了矩阵A的具体的值,所以线段树无需修改,只需要静态求最值,所以简单多了;
    至于二维的建法:以 (x) 轴为外部,对每个具体的 (x_i),对 (y) 轴去建它的子树 (sg[K].build(1,1,n)) ;
    然后! 当 (sg[K]) 每得到一个 (sg[K].ma[k]) 时,(up) 回去,就是 (sg[K>>1].ma[k]=max(sg[K>>1].ma[k],sg[K].ma[k])) ;
    这样就建好了!

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=2e3+5;
    const int inf=0x3f3f3f3f;
    
    ll a[maxn][maxn];
    int n;
    ll ma[maxn<<1][maxn<<1];
    struct SG1{
        void up(int K,int k)
        {
            ma[K>>1][k]=max(ma[K>>1][k],ma[K][k]);
            if(K>>1)up(K>>1,k);
        }
        void build(int K,int k,int l,int r,int y)
        {
            if(l==r)
            {
                ma[K][k]=a[l][y];
                up(K,k);
                return;
            }
            int mid=(l+r)>>1;
            build(K,k<<1,l,mid,y);build(K,k<<1|1,mid+1,r,y);
            ma[K][k]=max(ma[K][k<<1],ma[K][k<<1|1]);
            up(K,k);
        }
        ll query(int K,int k,int l,int r,int tl,int tr)
        {
            if(tl<=l&&r<=tr)return ma[K][k];
            int mid=(l+r)>>1;
            ll res=0;
            if(tl<=mid)res=query(K,k<<1,l,mid,tl,tr);
            if(tr>mid&&res<ma[K][k<<1|1])res=max(res,query(K,k<<1|1,mid+1,r,tl,tr));
            return res;
        }
    }sg;
    inline void build(int k,int l,int r)
    {
        if(l==r)
        {
            sg.build(k,1,1,n,l);
            return;
        }
        int mid=(l+r)>>1;
        build(k<<1,l,mid);build(k<<1|1,mid+1,r);
    }
    inline ll query(int k,int l,int r,int x1,int y1,int x2,int y2)
    {
        if(y1<=l&&r<=y2)return sg.query(k,1,1,n,x1,x2);
        int mid=(l+r)>>1;
        ll res=0;
        if(y1<=mid)res=query(k<<1,l,mid,x1,y1,x2,y2);
        if(y2>mid&&res<ma[k<<1|1][1])res=max(res,query(k<<1|1,mid+1,r,x1,y1,x2,y2));
        return res;
    }
    int main()
    {
        int m1,m2,x1,y1,x2,y2,w;
        scanf("%d%d%d",&n,&m1,&m2);
        while(m1--)
        {
            scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&w);
            a[x1][y1]+=w;a[x2+1][y2+1]+=w;
            a[x1][y2+1]-=w;a[x2+1][y1]-=w;
        }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                a[i][j]+=a[i-1][j]+a[i][j-1]-a[i-1][j-1];
        build(1,1,n);
        while(m2--)
        {
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            printf("%lld
    ",query(1,1,n,x1,y1,x2,y2));
        }
    }
    
    
  • 相关阅读:
    Docker篇章1:Docker介绍
    flask-restful结合vue自定义错误类型
    9.Go语言-函数
    8.Go语言-流程控制
    7.Go语言-结构体
    6.Go语言-指针
    5.Go语言-map类型
    计算机组成原理笔记2-数制、字符、校验码、定点数、浮点数、算术逻辑单元
    计算机组成原理笔记1--基础概念丶性能指标
    计算机网络笔记2--物理层
  • 原文地址:https://www.cnblogs.com/kkkek/p/12247443.html
Copyright © 2020-2023  润新知