【CodeForces】- 739C Alyona and towers

来源:互联网 发布:js获取两位小数函数 编辑:程序博客网 时间:2024/06/05 12:47

Alyona has built n towers by putting small cubes some on the top of others. Each cube has size 1 × 1 × 1. A tower is a non-zero amount of cubes standing on the top of each other. The towers are next to each other, forming a row.

Sometimes Alyona chooses some segment towers, and put on the top of each tower several cubes. Formally, Alyouna chooses some segment of towers from li to ri and adds di cubes on the top of them.

Let the sequence a1, a2, …, an be the heights of the towers from left to right. Let’s call as a segment of towers al, al + 1, …, ar a hill if the following condition holds: there is integer k (l ≤ k ≤ r) such that al < al + 1 < al + 2 < … < ak > ak + 1 > ak + 2 > … > ar.

After each addition of di cubes on the top of the towers from li to ri, Alyona wants to know the maximum width among all hills. The width of a hill is the number of towers in it.

Input

The first line contain single integer n (1 ≤ n ≤ 3·105) — the number of towers.

The second line contain n integers a1, a2, …, an (1 ≤ ai ≤ 109) — the number of cubes in each tower.

The third line contain single integer m (1 ≤ m ≤ 3·105) — the number of additions.

The next m lines contain 3 integers each. The i-th of these lines contains integers li, ri and di (1 ≤ l ≤ r ≤ n, 1 ≤ di ≤ 109), that mean that Alyona puts di cubes on the tio of each of the towers from li to ri.

Output

Print m lines. In i-th line print the maximum width of the hills after the i-th addition.

Solution

我们来定义一种特殊点,满足以下的条件

1、开头和结束的点
2、a[i]<a[i1],a[i+1]a[i]=a[i+1]

那么任意一个答案的区间不能跨过特殊点。
维护一个区间的最长答案,最左最右的特殊点。线段树即可。

(我还有一种鬼畜一点的做法,线段树上只维护一个值)
对于一个叶子节点,如果它是特殊点,它的值就是它到它左边的第一个特殊点的距离
(即以它为右端点的答案)
如果它不是特殊点,答案为0
树上维护最大值

这样的一棵线段树支持查询答案(根的值),查询前驱后继
修改的时候要查询前驱更新答案,还要去更新一下后继的答案
(:з」∠)

(ps:差分数组,修改会很舒服的~)
(注意数据范围……)

第一份是正常版的,第二份是鬼畜的(鬼畜跑得快)

#include<stdio.h>#include<algorithm>#define M 524287struct tree{int ans,l,r;} t[1050000];using namespace std;int l,n,r,p,m;long long a[300005];inline tree merge(const tree &x,const tree &y){    if ((!x.ans) && (!y.ans)) return (tree){0,0,0};    if (!x.ans) return y;if (!y.ans) return x;    return (tree){max(max(x.ans,y.ans),(x.r+1==y.l && !a[y.l])?1:y.l-x.r+1),x.l,y.r};}inline void judge(const int &i){    if (!(i && i<=n)) return;    if ((a[i]<=0 && 0<=a[i+1]) || (!a[i+1]) || (!a[i]) || i==1 || i==n) t[i+M]=(tree){1,i,i};    else t[i+M]=(tree){0,0,0};    for (int j=i+M>>1;j;j>>=1) t[j]=merge(t[j<<1],t[j<<1|1]);}int main(){    scanf("%d",&n);    for (int i=1;i<=n;i++) scanf("%d",a+i);    for (int i=n;i;i--) a[i]-=a[i-1];    for (int i=1;i<=n;i++) if ((a[i]<=0 && 0<=a[i+1]) || (!a[i+1]) || (!a[i]) || i==1 || i==n) t[i+M]=(tree){1,i,i};    else t[i+M]=(tree){0,0,0};    for (int i=M;i;i--) t[i]=merge(t[i<<1],t[i<<1|1]);    scanf("%d",&m);    while (m--)    {        scanf("%d%d%d",&l,&r,&p);        a[l]+=p;a[r+1]-=p;        judge(l-1);judge(l);judge(l+1);        judge(r);judge(r+1);judge(r+2);        printf("%d\n",t[1]);    }}
#include<stdio.h>#define M 524287inline int max(const int &a,const int &b){return a<b?b:a;}int l=1,n,r,p,t[1050000],m;long long a[300005];inline void judge(const int &l){    if (1<l && l<=n)    {        bool f=((a[l]<=0 && 0<=a[l+1]) || (!a[l+1]) || (!a[l])) || l==n;        int i=l+M-1,la=t[l+M];        if (f)        {            while (!t[i]) i=(i&1)?i>>1:i-1;            while (i<=M) i=t[i<<1|1]?i<<1|1:i<<1;        }        if (!a[i-M+1]) i++;        if (la!=(t[l+M]=f?l+M-i+1:0)) for (int i=l+M>>1;i;i>>=1) t[i]=max(t[i<<1],t[i<<1|1]);        return;    }}inline int getr(const int &r){    int i=r+M+1;    while (!t[i]) i=(i&1)?i+1:i>>1;    while (i<=M) i=t[i<<1]?i<<1:i<<1|1;    return i-M;}int main(){    scanf("%d",&n);a[n+1]=2333333333333333LL;    for (int i=1;i<=n;i++) scanf("%d",a+i);    for (int i=n;i;i--) a[i]-=a[i-1];    for (int i=2;i<n;i++) if ((a[i]<=0 && 0<=a[i+1]) || (!a[i+1]) || (!a[i]))    {        if (a[i]==0) l=i;        t[i+M]=i-l+1,l=i;    }    t[M+1]=1;t[n+M]=a[n]==0?1:n-l+1;    for (int i=M;i;i--) t[i]=max(t[i<<1],t[i<<1|1]);    scanf("%d",&m);    while (m--)    {        scanf("%d%d%d",&l,&r,&p);        a[l]+=p;a[r+1]-=p;        judge(l-1);        if (l<r) judge(l);        if (l+1<r) judge(l+1);        if (l+2<r) judge(getr(l+1));        judge(r);judge(r+1);judge(r+2);        if (r+2<n) judge(getr(r+2));        printf("%d\n",t[1]);    }}
0 0