bzoj 1513 树套树

来源:互联网 发布:淘宝购礼品盒 编辑:程序博客网 时间:2024/04/27 22:15

题意:每次把坐标系上的一个矩形内的权值修改成矩形内最大权值+w。求最后最大权值。

二维线段树,但外层数据结构既不能pushup(总不能重构内层树吧?),也不能pushdown(两个标记不能相加)。

我草,那怎么办?

标记永久化,打两种标记,第一种标记对经过的每一个点一路打下来,查询时精确查找。第二种标记恰好相反。

那么对于查找的区间在标记区间之上的情况会查到第一种标记,在标记之下的情况会查到第二种标记。

话说我以前似乎说过树套树外层不支持区间修改? flag秒收呀。。。

#include <bits/stdc++.h>using namespace std;#define N 3007#define ls l,mid,now<<1#define rs mid+1,r,now<<1|1int D,S,n,ans;int X1,Y1,X2,Y2;struct tree2{    int b1[N],b2[N];    int query(int l,int r,int now)    {        if(Y1<=l&&r<=Y2)return b1[now];        int mid=(l+r)>>1,ret=b2[now];        if(mid>=Y1)ret=max(ret,query(ls));        if(mid<Y2) ret=max(ret,query(rs));        return ret;    }    void update(int l,int r,int now,int v)    {        b1[now]=max(b1[now],v);        if(Y1<=l&&r<=Y2)        {b2[now]=max(b2[now],v);return;}        int mid=(l+r)>>1;        if(mid>=Y1)update(ls,v);        if(mid<Y2) update(rs,v);    }};struct tree1{    tree2 b1[N],b2[N];    int query(int l,int r,int now)    {        if(X1<=l&&r<=X2)            return b1[now].query(1,S,1);        int mid=(l+r)>>1,ret=b2[now].query(1,S,1);        if(mid>=X1)ret=max(ret,query(ls));        if(mid<X2) ret=max(ret,query(rs));        return ret;    }    void update(int l,int r,int now,int v)    {        b1[now].update(1,S,1,v);        if(X1<=l&&r<=X2)        {b2[now].update(1,S,1,v);return;}        int mid=(l+r)>>1;        if(mid>=X1)update(ls,v);        if(mid<X2) update(rs,v);    }}tr1;int main(){    //freopen("tt.in","r",stdin);    scanf("%d%d%d",&D,&S,&n);    for(int i=1,d,s,w,x,y;i<=n;i++)    {        scanf("%d%d%d%d%d",&d,&s,&w,&x,&y);        x++;y++;X1=x;Y1=y;X2=x+d-1;Y2=y+s-1;        int t=tr1.query(1,D,1);        tr1.update(1,D,1,t+w);        ans=max(ans,t+w);    }    printf("%d\n",ans);    return 0;}
0 0