codeforces #381 div2 E. Alyona and towers (线段树 区间合并)

e:题意:那个数,定义hill为一段连续的区间,满足该区间为严格单峰。现在有若干操作,每个操作是对某段区间的数同时增加一个数,问每次操作后,所有的hill中,宽度最大的(区间长度最大)的是多少。

思路:同时增加一个数很线段树。。。但是要维护什么呢。。。?

_猜测:肯定要维护一个区间中hill的最大宽度..._

但是合并的时候要怎么办呢。。。

考虑两个方向的合并。。。

所以还要维护一个区间中,包含右端点的向左单调减延伸的长度,以及左端点的值。

同理,要维护一个区间中,包含左端点的向右单调增延伸的长度,以及右端点的值。

那么每次pushup的时候,就是两个区间hill的最大值,以及两个方向合并的最大值中取最大。。。

。。。上面是我口胡的。。。

upd:

口胡的还是有点靠谱的(并没有2333,还是漏了情况)

具体题解见代码注释

以及,为了过这道题先过了在岛老师空间题解中提到的两道题目:

hdu 3308 题目链接

hdu 5367题目链接

  1/* ***********************************************
  2Author :111qqz
  3Created Time :2016年11月27日 星期日 22时16分44秒
  4File Name :code/cf/#381/E.cpp
  5************************************************ */
  6
  7#include <cstdio>
  8#include <cstring>
  9#include <iostream>
 10#include <algorithm>
 11#include <vector>
 12#include <queue>
 13#include <set>
 14#include <map>
 15#include <string>
 16#include <cmath>
 17#include <cstdlib>
 18#include <ctime>
 19#define fst first
 20#define sec second
 21#define lson l,m,rt<<1
 22#define rson m+1,r,rt<<1|1
 23#define ms(a,x) memset(a,x,sizeof(a))
 24typedef long long LL;
 25#define pi pair < int ,int >
 26#define MP make_pair
 27
 28using namespace std;
 29const double eps = 1E-8;
 30const int dx4[4]={1,0,0,-1};
 31const int dy4[4]={0,-1,1,0};
 32const int inf = 0x3f3f3f3f;
 33const int N=3E5+7;
 34int a[N];
 35int n,m;
 36struct Tree
 37{
 38    LL lm,rm;//左右端点值。
 39    int ans,len,upL,upR,downL,downR,maxL,maxR;
 40    /* 分别为
 41     * ans:区间最优解
 42     * len:区间长度
 43     * upL,downL,maxL:包含左端点的递增,递减,山型的长度
 44     * upR,downR,maxR: 包含右端点的递增,递减,山型的长度
 45     */
 46    Tree()
 47    {
 48	ans = len = upL = upR = downL = downR = maxL = maxR = lm = rm = 0;
 49    }
 50    Tree( int x)
 51    {
 52	ans = len = upL = upR = downL = downR = maxL = maxR = 1;
 53	lm = rm = x;
 54    }
 55};
 56
 57Tree operator + ( Tree x,Tree y) //x为左子树所表示的区间,y为右子树所表示的区间
 58{
 59    Tree res;
 60    if (x.rm>y.lm)
 61    {
 62	res.ans = max(x.ans,y.ans);
 63	res.len = x.len + y.len;//区间长度这个变量也可以不放在线段树的域中,而是每次pushUp和pushdown的时候传参数进去。
 64	res.upL = x.upL;
 65	res.upR = y.upR;
 66	res.downL = x.downL +(x.downL==x.len) * (y.downL);//如果左区间全都递减,那么新区间包含左端点的递减长度可以把右区间包含左端点的递减长度包含进来。
 67	res.downR = y.downR + (y.downR==y.len) *(x.downR);//如果右区间全都递减,那么新区间包含右端点的递减长度可以把左区间包含右端点的递减长度包含进来。
 68	res.lm = x.lm;
 69	res.rm = y.rm; //更新端点值
 70	res.ans = max(res.ans,x.maxR+y.downL);//左区间包含右端点的山型可以再接一部分右区间包含左端点的下降序列,仍然是山型。
 71	res.maxL = x.maxL + (x.maxL == x.len) *(y.downL);//新区间包含左端点的山形在左区间都是山型的时候可以把右区间包含左端点的下降序列包含进来。
 72	res.maxR = y.maxR +(y.downL == y.len) *(x.maxR);//新区间包含右端点的山形 在右区间都是下降的时候可以把左区间包含右端点的山形序列包含进来。
 73
 74    }
 75    else if (x.rm<y.lm)//同上,只是方向相反。
 76    {
 77	res.ans = max(x.ans,y.ans);
 78	res.len = x.len + y.len;
 79	res.upL = x.upL +(x.upL == x.len)*(y.upL);
 80	res.upR = y.upR +(y.upR == y.len)*(x.upR);
 81	res.downL = x.downL;
 82	res.downR = y.downR;
 83	res.lm = x.lm;
 84	res.rm = y.rm;
 85	res.ans = max(res.ans,x.upR + y.maxL);
 86	res.maxL = x.maxL + (x.upL==x.len)*(y.maxL);
 87	res.maxR = y.maxR + (y.maxR==y.len)*(x.upR);	
 88    }
 89    else //不要忘记相等的情况。
 90    {
 91	res.ans = max(x.ans,y.ans);
 92	res.len = x.len + y.len;
 93	res.upL = x.upL;
 94	res.upR = y.upR;
 95	res.downL = x.downL;
 96	res.downR = y.downR;
 97	res.lm = x.lm;
 98	res.rm = y.rm;
 99	res.maxL = x.maxL;
100	res.maxR = y.maxR;
101
102    }
103    return res;
104}
105Tree tree[N<<2];
106LL lazy[N<<2];
107void doit(int rt,LL v)
108{
109    lazy[rt]+=v;
110    tree[rt].lm += v;
111    tree[rt].rm += v;
112}
113void PushDown(int rt)
114{
115    if (lazy[rt])
116    {
117	doit(rt<<1,lazy[rt]);
118	doit(rt<<1|1,lazy[rt]);
119	lazy[rt] = 0 ;
120    }
121}
122void build( int l,int r,int rt)
123{
124  //  cout<<l<<" "<<r<<" "<<rt<<endl;
125    if (l==r)
126    {
127	tree[rt] = Tree(a[l]);
128	return ;	
129    }
130
131    int m = (l+r)>>1;
132    build(lson);
133    build(rson);
134    tree[rt] = tree[rt<<1] + tree[rt<<1|1];
135}
136
137void update(int L,int R,int d,int l,int r,int rt)
138{
139    if (L<=l&&r<=R)
140    {
141	doit(rt,d);
142	return;
143    }
144    PushDown(rt);
145    int m = (l+r)>>1;
146    if (L<=m)
147    update(L,R,d,lson);
148    if (R>=m+1)
149    update(L,R,d,rson);
150    tree[rt] = tree[rt<<1] + tree[rt<<1|1];
151}
152
153int main()
154{
155	#ifndef  ONLINE_JUDGE 
156	freopen("code/in.txt","r",stdin);
157  #endif
158	cin>>n;
159	for ( int i = 1;  i <= n ; i++) scanf("%d",&a[i]);
160	cin>>m;
161	build(1,n,1);
162	while (m--)
163	{
164	    int l,r,d;
165	    scanf("%d%d%d",&l,&r,&d);
166	    update(l,r,d,1,n,1);
167	    printf("%d\n",tree[1].ans);
168	}
169
170  #ifndef ONLINE_JUDGE  
171  fclose(stdin);
172  #endif
173    return 0;
174}