【线段树】牛客 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));
    }
}

原文地址:https://www.cnblogs.com/kkkek/p/12247443.html