P4314 CPU监控

传送门:https://www.luogu.com.cn/problem/P4314

题意:

给出 T 个数,E 个操作(T,E 10^5):

Q X Y:询问从 X 到 Y 的当前最大值

A X Y:询问从 X 到 Y 的历史最大值(出现过的最大数

P X Y Z:将 X 到 Y 这段区间加 Z

C X Y Z:将 X 到 Y 这段区间赋值为 Z

这个题,第一反应就是线段树

如果你是信心满满的用当前最大值及当前的标记维护历史最大值,你就会wa掉了

仔细想想这个历史最大值,如果按照最初的写法,先add,再cover,那么当前sum还没有更新sum+add就被覆盖了,历史最大值就不准确了

但你是不是又想在add之前把所有标记下放??

这样的话lazy标记就失去意义了,时间复杂度翻倍的上升,会 tle8个点 应该

呐 这个标记的方式就很巧妙了

struct node 
{
    int l,r,add,cov,sum,evsum,evadd,evcov,is_cov;
}tree[maxn*4];
基本的元素有l,r,add,cov
我们后添加的有 evsum(历史最大值)evadd(历史添加的最大值),evcov(历史覆盖最大值),is_cov(是否被覆盖过)
我们在下放标记更新sum的同时 用evxxx继续更新evsum
而且是实时下放标记,没有判断条件
重点是push_down,如何下放标记
 
分类讨论
1 加操作 对于他的两个儿子
如果被覆盖过,那么覆盖cov之后再加add,就相当于是覆盖了cov+add,更新evcov,evsum
 //左儿子为例
tree[now<<1].evcov=max(tree[now<<1].evcov,tree[now<<1].cov+tree[now].evadd);
tree[now<<1].evsum=max(tree[now<<1].evsum,tree[now<<1].cov+tree[now].evadd);
tree[now<<1].sum=tree[now<<1].cov=tree[now<<1].cov+tree[now].add;
tree[now<<1].add=0;
如果没有覆盖过,那就是加上一个add   更新evadd,evsum
 //左儿子为例
tree[now<<1].evadd=max(tree[now<<1].evadd,tree[now<<1].add+tree[now].evadd); tree[now<<1].evsum=max(tree[now<<1].evsum,tree[now<<1].sum+tree[now].evadd);
   tree[now<<1].add+=tree[now].add;
   tree[now<<1].sum+=tree[now].add;
记得清空标记
 
2 覆盖操作 对于他的两个儿子
如果被覆盖过,覆盖了cov,同时取最大值更新evcov,evsum
如果没有被覆盖过,把is_cov标记为1,把cov覆盖上去,更新evcov,evsum
 
if(tree[now<<1].is_cov)//以左儿子为例
{
    tree[now<<1].evcov=max(tree[now<<1].evcov,tree[now].evcov);
}
else 
{
    tree[now<<1].is_cov=1;
    tree[now<<1].evcov=tree[now].evcov;
}
tree[now<<1].evsum=max(tree[now<<1].evsum,tree[now].evcov);
tree[now<<1].cov=tree[now<<1].sum=tree[now].cov;
tree[now<<1].add=0;

 

关于怎么覆盖值得好好考虑,再就是要认清楚,他的本质是同时更新sum和evsum,把他们分开 自己考虑自己的就不会乱
 
对于sum的更新就正常来就好了,每次的cover操作过后add也就该请零了
 
240+行,这可真是我写除了模拟的最长代码,破了前天的记录
虽然东西有点多,但思路很清晰
仔细一点争取不用debug,不然绝对会崩溃的 (;´д`)ゞ
 
  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 #define ll long long
  4 #define lowbit(a) ((a) & -(a))
  5 #define clean(a, b) memset(a, b, sizeof(a))
  6 const int inf = 0x3f3f3f3f;
  7 const int maxn = 1e5 + 10;
  8 int _;
  9 
 10 /////////////////////////////////////////////////////////////////
 11 char s[10];
 12 int a[maxn];
 13 struct node 
 14 {
 15     int l,r,add,cov,sum,evsum,evadd,evcov,is_cov;
 16 }tree[maxn*4];
 17 void build(int l,int r,int now)
 18 {
 19     tree[now].l=l;
 20     tree[now].r=r;
 21     tree[now].sum=tree[now].evsum=-inf;
 22     if(l==r)
 23     {
 24         tree[now].sum=a[l];
 25         tree[now].evsum=a[l];
 26         return ;
 27     }
 28     int mid=(l+r)>>1;
 29     build(l,mid,now<<1);
 30     build(mid+1,r,now<<1|1);
 31     tree[now].evsum=tree[now].sum=max(tree[now<<1].sum,tree[now<<1|1].sum);
 32 }
 33 void push_down_add(int now)
 34 {
 35     if(tree[now<<1].is_cov) 
 36     {
 37         tree[now<<1].evcov=max(tree[now<<1].evcov,tree[now<<1].cov+tree[now].evadd);
 38         tree[now<<1].evsum=max(tree[now<<1].evsum,tree[now<<1].cov+tree[now].evadd);
 39         tree[now<<1].sum=tree[now<<1].cov=tree[now<<1].cov+tree[now].add;
 40         tree[now<<1].add=0;
 41     }
 42     else 
 43     {
 44         tree[now<<1].evadd=max(tree[now<<1].evadd,tree[now<<1].add+tree[now].evadd);
 45         tree[now<<1].evsum=max(tree[now<<1].evsum,tree[now<<1].sum+tree[now].evadd);
 46         tree[now<<1].add+=tree[now].add;
 47         tree[now<<1].sum+=tree[now].add;
 48     }
 49     
 50     if(tree[now<<1|1].is_cov)
 51     {
 52         tree[now<<1|1].evcov=max(tree[now<<1|1].evcov,tree[now<<1|1].cov+tree[now].evadd);
 53         tree[now<<1|1].evsum=max(tree[now<<1|1].evsum,tree[now<<1|1].cov+tree[now].evadd);
 54         tree[now<<1|1].sum=tree[now<<1|1].cov=tree[now<<1|1].cov+tree[now].add;
 55         tree[now<<1|1].add=0;
 56     }
 57     else 
 58     {
 59         tree[now<<1|1].evadd=max(tree[now<<1|1].evadd,tree[now<<1|1].add+tree[now].evadd);
 60         tree[now<<1|1].evsum=max(tree[now<<1|1].evsum,tree[now<<1|1].sum+tree[now].evadd);
 61         tree[now<<1|1].add+=tree[now].add;
 62         tree[now<<1|1].sum+=tree[now].add;
 63     }
 64 
 65     tree[now].add=tree[now].evadd=0;
 66 
 67 }
 68 void push_down_cover(int now)
 69 {
 70     if(tree[now].is_cov)
 71     {
 72         if(tree[now<<1].is_cov)
 73         {
 74             tree[now<<1].evcov=max(tree[now<<1].evcov,tree[now].evcov);
 75         }
 76         else 
 77         {
 78             tree[now<<1].is_cov=1;
 79             tree[now<<1].evcov=tree[now].evcov;
 80         }
 81         tree[now<<1].evsum=max(tree[now<<1].evsum,tree[now].evcov);
 82         tree[now<<1].cov=tree[now<<1].sum=tree[now].cov;
 83         tree[now<<1].add=0;
 84         
 85         if(tree[now<<1|1].is_cov)
 86         {
 87             tree[now<<1|1].evcov=max(tree[now<<1|1].evcov,tree[now].evcov);
 88         }
 89         else 
 90         {
 91             tree[now<<1|1].is_cov=1;
 92             tree[now<<1|1].evcov=tree[now].evcov;
 93         }
 94         tree[now<<1|1].evsum=max(tree[now<<1|1].evsum,tree[now].evcov);
 95         tree[now<<1|1].cov=tree[now<<1|1].sum=tree[now].cov;
 96         tree[now<<1|1].add=0;
 97 
 98         tree[now].is_cov=tree[now].cov=tree[now].evcov=0;
 99     }
100 }
101 void push_down(int now)
102 { 
103     push_down_add(now);
104     push_down_cover(now);  
105 }
106 void update(int l,int r,int x,int now)
107 {
108     if(l==tree[now].l&&r==tree[now].r)
109     {
110         if(tree[now].is_cov)
111         {
112             tree[now].evcov=max(tree[now].evcov,x);
113         }
114         else 
115         {
116             tree[now].is_cov=1;
117             tree[now].evcov=x;
118         }
119         tree[now].evsum=max(tree[now].evsum,x);
120         tree[now].cov=tree[now].sum=x;
121         tree[now].add=0;
122         return ;
123     }
124     push_down(now);
125     int mid=(tree[now].l+tree[now].r)>>1;
126     if(r<=mid) update(l,r,x,now<<1);
127     else if(l>mid) update(l,r,x,now<<1|1);
128     else 
129     {
130         update(l,mid,x,now<<1);
131         update(mid+1,r,x,now<<1|1);
132     }
133     tree[now].sum=max(tree[now<<1].sum,tree[now<<1|1].sum);
134     tree[now].evsum=max(tree[now].evsum,tree[now].sum);
135 }
136 void addition(int l,int r,int x,int now)
137 {
138     if(l==tree[now].l&&r==tree[now].r)
139     {
140         if(tree[now].is_cov) 
141         {
142             tree[now].evcov=max(tree[now].evcov,tree[now].cov+x);
143             tree[now].evsum=max(tree[now].evsum,tree[now].cov+x);
144             tree[now].cov=tree[now].sum=tree[now].cov+x;
145             tree[now].add=0;
146         }
147         else 
148         {
149             tree[now].evadd=max(tree[now].evadd,tree[now].add+x);
150             tree[now].evsum=max(tree[now].evsum,tree[now].sum+x);
151             tree[now].add+=x;
152             tree[now].sum+=x;
153         }
154         return ;
155     }
156     push_down(now);
157     int mid=(tree[now].l+tree[now].r)>>1;
158     if(r<=mid) addition(l,r,x,now<<1);
159     else if(l>mid) addition(l,r,x,now<<1|1);
160     else 
161     {
162         addition(l,mid,x,now<<1);
163         addition(mid+1,r,x,now<<1|1);
164     }
165     tree[now].sum=max(tree[now<<1].sum,tree[now<<1|1].sum);
166     tree[now].evsum=max(tree[now].evsum,tree[now].sum);
167 }
168 int query(int l,int r,int now)
169 {
170     if(l==tree[now].l&&r==tree[now].r)
171     {
172         return tree[now].sum;
173     }
174     push_down(now);
175     int mid=(tree[now].l+tree[now].r)>>1;
176     int maxx=-inf;
177     if(r<=mid) maxx=max(maxx,query(l,r,now<<1));
178     else if(l>mid) maxx=max(maxx,query(l,r,now<<1|1));
179     else 
180     {
181         maxx=max(maxx,query(l,mid,now<<1));
182         maxx=max(maxx,query(mid+1,r,now<<1|1));
183     }
184     return maxx;
185 }
186 int querymax(int l,int r,int now)
187 {
188     if(l==tree[now].l&&r==tree[now].r)
189     {
190         return tree[now].evsum;
191     }
192     push_down(now);
193     int mid=(tree[now].l+tree[now].r)>>1;
194     int maxx=-inf;
195     if(r<=mid) maxx=max(maxx,querymax(l,r,now<<1));
196     else if(l>mid) maxx=max(maxx,querymax(l,r,now<<1|1));
197     else 
198     {
199         maxx=max(maxx,querymax(l,mid,now<<1));
200         maxx=max(maxx,querymax(mid+1,r,now<<1|1));
201     }
202     return maxx;
203 }
204 ///////////////////////////////////////////////////////////////// 
205 int main()
206 {
207     // freopen("in.in","r",stdin);
208     int t,q;
209     scanf("%d",&t);
210     for(int i=1;i<=t;i++)
211     {
212         scanf("%d",&a[i]);
213     }
214     build(1,t,1);
215     scanf("%d",&q);
216     for(int i=1;i<=q;i++)
217     {
218         scanf("%s",s);
219         int x,y,z;
220         if(s[0]=='Q')//the max
221         {
222             scanf("%d%d",&x,&y);
223             int ans=query(x,y,1);
224             printf("%d\n",ans);
225         }
226         if(s[0]=='A')//Ever largest
227         {
228             scanf("%d%d",&x,&y);
229             int ans=querymax(x,y,1);
230             printf("%d\n",ans);
231         }
232         if(s[0]=='P')
233         {
234             scanf("%d%d%d",&x,&y,&z);
235             addition(x,y,z,1);
236         }
237         if(s[0]=='C')
238         {
239             scanf("%d%d%d",&x,&y,&z);
240             update(x,y,z,1);
241         }
242     }
243     return 0;
244 }

 

 
 
 
 
 
posted @ 2020-04-30 21:14  L·S·D  阅读(289)  评论(0编辑  收藏  举报