BZOJ3064: Tyvj 1518 CPU监控

n<=100000的数列支持以下操作:一、区间加;二、区间赋值;三、查区间最大;四、查区间历史版本最大。

恶心死我了。。可能很水,但我调了半天。

错误!调了两天。

这里有一个棘手问题:历史版本。

首先不看赋值操作。记俩标记——区间加add和区间历史加标记pre。其中后者的含义是“从上一次这个区间标记下传到现在,区间加(前者)标记的最大值”。这样,比如某点i的标记下传给儿子x,标记如此叠加:$pre_x>?=pre_i+add_x$,$add_x+=add_i$,同时更新区间历史版本最大值:$his_x>?=Max_x+pre_x-add_x$。

然后加入赋值操作。可以发现一个区间在标记下传前只有两个阶段:一开始只有加标记,后来只有赋值标记:打上赋值标记后,如果该区间还要加,相当于更新赋值标记。因此,分两种历史标记来搞,一个记第一阶段的$add$的最大值,一个记第二阶段$be$的最大值。下传时注意顺序。

关键点截图留念:

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<cstdio>
  5 #include<math.h>
  6 //#include<complex>
  7 //#include<ctime>
  8 #include<algorithm>
  9 using namespace std;
 10 
 11 int n,m;
 12 #define maxn 100011
 13 const int inf=0x3f3f3f3f;
 14 int num[maxn];
 15 struct SMT
 16 {
 17     struct Node
 18     {
 19         int ls,rs;
 20         int add,pa,be,pb;
 21         int Max,pmax;
 22     }a[maxn<<1];
 23     int size,root;
 24     SMT() {size=root=0; a[0].Max=a[0].pmax=-inf;}
 25     void up(int x,int L,int R)
 26     {
 27         int &p=a[x].ls,&q=a[x].rs;
 28         a[x].Max=max(a[p].Max,a[q].Max);
 29         a[x].pmax=max(a[p].pmax,a[q].pmax);
 30     }
 31     void addsingle(int x,int L,int R,int v,int pv)
 32     {
 33         if (a[x].be!=-inf)
 34         {besingle(x,L,R,a[x].be+v,a[x].be+pv); return;}
 35         a[x].pa=max(a[x].pa,a[x].add+pv),a[x].add+=v;
 36         a[x].Max+=v; a[x].pmax=max(a[x].pmax,a[x].pa+a[x].Max-a[x].add);
 37     }
 38     void besingle(int x,int L,int R,int v,int pv)
 39     {
 40         a[x].pb=max(a[x].pb,pv); a[x].add=0; a[x].be=v;
 41         a[x].Max=v; a[x].pmax=max(a[x].pmax,a[x].pb);
 42     }
 43     void down(int x,int L,int R)
 44     {
 45         int &p=a[x].ls,&q=a[x].rs,mid=(L+R)>>1;
 46         if (a[x].add || a[x].pa)
 47         addsingle(p,L,mid,a[x].add,a[x].pa),addsingle(q,mid+1,R,a[x].add,a[x].pa),a[x].add=a[x].pa=0;
 48         if (a[x].be!=-inf || a[x].pb!=-inf)
 49         besingle(p,L,mid,a[x].be,a[x].pb),besingle(q,mid+1,R,a[x].be,a[x].pb),a[x].be=a[x].pb=-inf;
 50     }
 51     void build(int &x,int L,int R)
 52     {
 53         x=++size;
 54         a[x].add=a[x].pa=0; a[x].be=a[x].pb=-inf; 
 55         if (L==R) {a[x].ls=a[x].rs=0; a[x].Max=a[x].pmax=num[L];return;}
 56         int mid=(L+R)>>1;
 57         build(a[x].ls,L,mid); build(a[x].rs,mid+1,R); up(x,L,R);
 58     }
 59     void build() {build(root,1,n);}
 60     int ql,qr,v;
 61     void Add(int &x,int L,int R)
 62     {
 63         if (ql<=L && R<=qr) {addsingle(x,L,R,v,v); return;}
 64         down(x,L,R);
 65         int mid=(L+R)>>1;
 66         if (ql<=mid) Add(a[x].ls,L,mid);
 67         if (qr> mid) Add(a[x].rs,mid+1,R);
 68         up(x,L,R);
 69     }
 70     void add(int L,int R,int v)
 71     {
 72         ql=L; qr=R; this->v=v;
 73         Add(root,1,n);
 74     }
 75     void Be(int &x,int L,int R)
 76     {
 77         if (ql<=L && R<=qr) {besingle(x,L,R,v,v); return;}
 78         down(x,L,R);
 79         int mid=(L+R)>>1;
 80         if (ql<=mid) Be(a[x].ls,L,mid);
 81         if (qr> mid) Be(a[x].rs,mid+1,R);
 82         up(x,L,R);
 83     }
 84     void be(int L,int R,int v)
 85     {
 86         ql=L; qr=R; this->v=v;
 87         Be(root,1,n);
 88     }
 89     int Qmax(int &x,int L,int R)
 90     {
 91         if (ql<=L && R<=qr) return a[x].Max;
 92         down(x,L,R);
 93         int mid=(L+R)>>1,ans=-inf;
 94         if (ql<=mid) ans=Qmax(a[x].ls,L,mid);
 95         if (qr> mid) ans=max(ans,Qmax(a[x].rs,mid+1,R));
 96         return ans;
 97     }
 98     int qmax(int L,int R)
 99     {
100         ql=L; qr=R;
101         return Qmax(root,1,n);
102     }
103     int Qpmax(int &x,int L,int R)
104     {
105         if (ql<=L && R<=qr) return a[x].pmax;
106         down(x,L,R);
107         int mid=(L+R)>>1,ans=-inf;
108         if (ql<=mid) ans=Qpmax(a[x].ls,L,mid);
109         if (qr> mid) ans=max(ans,Qpmax(a[x].rs,mid+1,R));
110         return ans;
111     }
112     int qpmax(int L,int R)
113     {
114         ql=L; qr=R;
115         return Qpmax(root,1,n);
116     }
117 }t;
118 
119 int main()
120 {
121     scanf("%d",&n);
122     for (int i=1;i<=n;i++) scanf("%d",&num[i]);
123     t.build();
124     
125     scanf("%d",&m);
126     int x,y,z; char id;
127     while (m--)
128     {
129         while ((id=getchar())<'A' || id>'Z');
130         if (id=='A') scanf("%d%d",&x,&y),printf("%d\n",t.qpmax(x,y));
131         else if (id=='Q') scanf("%d%d",&x,&y),printf("%d\n",t.qmax(x,y));
132         else if (id=='P') scanf("%d%d%d",&x,&y,&z),t.add(x,y,z);
133         else scanf("%d%d%d",&x,&y,&z),t.be(x,y,z);
134     }
135     return 0;
136 }
View Code

 

转载于:https://www.cnblogs.com/Blue233333/p/8448451.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值