• 数据结构:树套树-线段树套线段树


    BZOJ1513

    我们经常提及的二维线段树有两种写法,一种是四分树,一种是树套树,写成四分树的都是神仙。

    树套树写法还是比较好理解的,不过要是让自己硬套的话可能很不容易套出来的

    这里的二维线段树,外层线段树是对方阵的正投影,而内层线段树是对方阵的侧投影

    这里的内层线段树可以变换成一棵普通的带lazy tag的线段树,外层的应该很难吧

    然后,介绍一下怎么写:

    int D,S,N,ql,qr,qd,qu;

    D是矩阵长,S是矩阵宽,N是修改(修改内嵌查询)的次数,然后ql,qr,qd,qu表示每一次修改区间的四个端点

    我们看内层线段树,内层线段树其实就是维护了一个最值

    struct segx
    {
        int v[3005],tag[3005];
        void change(int k,int l,int r,int x,int y,int val)
        {
            v[k]=max(v[k],val);
            if(l==x&&y==r) {tag[k]=max(tag[k],val);return;}
            int mid=(l+r)>>1;
            if(x<=mid) change(k<<1,l,mid,x,min(mid,y),val);
            if(y>mid) change(k<<1|1,mid+1,r,max(x,mid+1),y,val);
        }
        int query(int k,int l,int r,int x,int y)
        {
            if(l==x&&y==r) return v[k];
            int mid=(l+r)>>1,ans=tag[k];
            if(x<=mid) ans=max(ans,query(k<<1,l,mid,x,min(mid,y)));
            if(y>mid) ans=max(ans,query(k<<1|1,mid+1,r,max(x,mid+1),y));
            return ans;

    如果不是追求极限的做法,直接这样就可以了了,没必要加上lazytag,因为那样应该不是题目重点(除非是出题人,有脑洞。。)

    然后是外层线段树,这里的衔接还是比较自然地,不像别的树套树,可以这么形容一下,别的树套树衔接都是带锯齿的,这里是平滑的

    struct segy
    {
        segx v[3005],tag[3005];
        void change(int k,int l,int r,int x,int y,int val)
        {
            v[k].change(1,1,S,qd,qu,val);
            if(l==x&&y==r) {tag[k].change(1,1,S,qd,qu,val);return;}
            int mid=(l+r)>>1;
            if(x<=mid) change(k<<1,l,mid,x,min(mid,y),val);
            if(y>mid) change(k<<1|1,mid+1,r,max(x,mid+1),y,val);
        }
        int query(int k,int l,int r,int x,int y)
        {
            if(l==x&&y==r) return v[k].query(1,1,S,qd,qu);
            int mid=(l+r)>>1,ans=tag[k].query(1,1,S,qd,qu);
            if(x<=mid) ans=max(ans,query(k<<1,l,mid,x,min(mid,y)));
            if(y>mid) ans=max(ans,query(k<<1|1,mid+1,r,max(x,mid+1),y));
            return ans;
        }
    }T;

    我们可以看到内外还是比较协调统一的,最后给出完整实现:

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 int D,S,N,ql,qr,qd,qu;
     5 long long read()
     6 {
     7     long long x=0,f=1;char ch=getchar();
     8     while(ch<'0'||ch>'9') {if(ch=='-')f=-1; ch=getchar();}
     9     while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
    10     return x*f;
    11 }
    12 struct segx
    13 {
    14     int v[3005],tag[3005];
    15     void change(int k,int l,int r,int x,int y,int val)
    16     {
    17         v[k]=max(v[k],val);
    18         if(l==x&&y==r) {tag[k]=max(tag[k],val);return;}
    19         int mid=(l+r)>>1;
    20         if(x<=mid) change(k<<1,l,mid,x,min(mid,y),val);
    21         if(y>mid) change(k<<1|1,mid+1,r,max(x,mid+1),y,val);
    22     }
    23     int query(int k,int l,int r,int x,int y)
    24     {
    25         if(l==x&&y==r) return v[k];
    26         int mid=(l+r)>>1,ans=tag[k];
    27         if(x<=mid) ans=max(ans,query(k<<1,l,mid,x,min(mid,y)));
    28         if(y>mid) ans=max(ans,query(k<<1|1,mid+1,r,max(x,mid+1),y));
    29         return ans;
    30     }
    31 };
    32 struct segy
    33 {
    34     segx v[3005],tag[3005];
    35     void change(int k,int l,int r,int x,int y,int val)
    36     {
    37         v[k].change(1,1,S,qd,qu,val);
    38         if(l==x&&y==r) {tag[k].change(1,1,S,qd,qu,val);return;}
    39         int mid=(l+r)>>1;
    40         if(x<=mid) change(k<<1,l,mid,x,min(mid,y),val);
    41         if(y>mid) change(k<<1|1,mid+1,r,max(x,mid+1),y,val);
    42     }
    43     int query(int k,int l,int r,int x,int y)
    44     {
    45         if(l==x&&y==r) return v[k].query(1,1,S,qd,qu);
    46         int mid=(l+r)>>1,ans=tag[k].query(1,1,S,qd,qu);
    47         if(x<=mid) ans=max(ans,query(k<<1,l,mid,x,min(mid,y)));
    48         if(y>mid) ans=max(ans,query(k<<1|1,mid+1,r,max(x,mid+1),y));
    49         return ans;
    50     }
    51 }T;
    52 int main()
    53 {
    54     D=read();S=read();N=read();
    55     int d,s,w,x,y;
    56     for(int i=1;i<=N;i++)
    57     {
    58         d=read();s=read();w=read();x=read();y=read();
    59         ql=x+1;qr=x+d;qd=y+1;qu=y+s;
    60         int ans=T.query(1,1,D,ql,qr);
    61         T.change(1,1,D,ql,qr,ans+w);
    62     }
    63     qd=1,qu=S;
    64     printf("%d
    ",T.query(1,1,D,1,D));
    65     return 0;
    66 }
  • 相关阅读:
    [转][Navicat for MySQL系列]Navicat如何使用(二)
    [转]Syntax error on token "Invalid Character", delete this token 的解决
    [转] valuestack,stackContext,ActionContext.之间的关系
    [转]jquery后代和子元素的区别
    python中模块、包、库的区别和使用
    python函数对象
    list深拷贝和浅拷贝
    json中load和loads区别
    变量作用域
    正则里的.*和.*?区别
  • 原文地址:https://www.cnblogs.com/aininot260/p/9375048.html
Copyright © 2020-2023  润新知