codeforces 739C 线段树的高级应用

来源:互联网 发布:java编程培训教程 编辑:程序博客网 时间:2024/06/08 02:41

题意,给你一个序列,有q次操作,每次对一个区间进行加值,同时要输出 最长的上升序列/下降序列/先上升再下降序列

很明显能想到的是利用线段树维护,有很明显的能想到要维护线段树的每个区间的左边界和右边界的值,并且每个点都有维护四种变化的值,然后就懵逼了。
这时候应该想到的是维护每个区间的左右边界的四种情况进行拼凑来更新
一开始想到的是单峰,对于多峰没想到如何维护,其实也是很简单,有点类似拼图或者插头dp,因为每次子树的合并会对会造成影响的情况不多,从左边开始的单调和从左边开始的双调还有从右边开始的单调和从右边开始的双调,以及中间的单调和双调的合并。
这里写图片描述

可以知道下面的四种情况其实只有可以种处理的,那么就是 下面贴代码,mx1代表单调, mx2代表双调
l,r代表是从左还是右边界开始的

#include <bits/stdc++.h>using namespace std;const int N = 3e5+100;typedef long long ll;int mx1l[N<<2],mx1r[N<<2],mx2l[N<<2],mx2r[N<<2],mx2[N<<2];ll vl[N<<2],vr[N<<2],tag[N<<2];int a[N],sz[N<<2];void pushdown(int rt){    if(tag[rt])    {        vl[rt<<1]+=tag[rt];        vl[rt<<1|1]+=tag[rt];        vr[rt<<1]+=tag[rt];        vr[rt<<1|1]+=tag[rt];        tag[rt<<1]+=tag[rt];        tag[rt<<1|1]+=tag[rt];        tag[rt]=0;    }}void pushup(int rt){    vl[rt]=vl[rt<<1];    vr[rt]=vr[rt<<1|1];    int v2=0;    mx2[rt]=max(mx2[rt<<1],mx2[rt<<1|1]);    mx1l[rt]=mx1l[rt<<1];    if(mx1l[rt<<1]==sz[rt<<1]&&vr[rt<<1]>vl[rt<<1|1]) mx1l[rt]+=mx1l[rt<<1|1];    // mx1l[rt]=max(mx1l[rt],mx1l[rt<<1|1]);    mx2[rt]=max(mx2[rt],mx1l[rt]);    mx1r[rt]=mx1r[rt<<1|1];    if(mx1r[rt<<1|1]==sz[rt<<1|1]&&vr[rt<<1]<vl[rt<<1|1]) mx1r[rt]+=mx1r[rt<<1];    // mx1r[rt]=max(mx1r[rt],mx1r[rt<<1]);    mx2[rt]=max(mx2[rt],mx1r[rt]);    mx2l[rt]=mx2l[rt<<1];    if(mx2l[rt<<1]==sz[rt<<1]&&vr[rt<<1]>vl[rt<<1|1]) mx2l[rt]+=mx1l[rt<<1|1];    mx2[rt]=max(mx2[rt],mx2l[rt]);    if(mx1r[rt<<1]==sz[rt<<1]&&vr[rt<<1]<vl[rt<<1|1]) v2=mx1r[rt<<1]+mx2l[rt<<1|1];    mx2l[rt]=max(mx2l[rt],v2);    v2=0;    mx2r[rt]=mx2r[rt<<1|1];    if(mx2r[rt<<1|1]==sz[rt<<1|1]&&vl[rt<<1|1]>vr[rt<<1]) mx2r[rt]+=mx1r[rt<<1];    mx2[rt]=max(mx2[rt],mx2r[rt]);    if(mx1l[rt<<1|1]==sz[rt<<1|1]&&vr[rt<<1]>vl[rt<<1|1]) v2=mx1l[rt<<1|1]+mx2r[rt<<1];    mx2r[rt]=max(mx2r[rt],v2);    mx2[rt]=max(mx2[rt],max(mx2l[rt],mx2r[rt]));    if(vl[rt<<1|1]>vr[rt<<1]) mx2[rt]=max(mx2[rt],mx1r[rt<<1]+mx2l[rt<<1|1]);    if(vl[rt<<1|1]<vr[rt<<1]) mx2[rt]=max(mx2[rt],mx2r[rt<<1]+mx1l[rt<<1|1]);}void update(int L,int R,int l,int r,int rt,ll x){    if(L<=l&&R>=r)    {        vl[rt]+=x;        vr[rt]+=x;        tag[rt]+=x;        return ;    }    pushdown(rt);    int mid=(l+r)>>1;    if(L<=mid) update(L,R,l,mid,rt<<1,x);    if(R>mid) update(L,R,mid+1,r,rt<<1|1,x);    pushup(rt);}void build(int l,int r,int rt){    sz[rt]=r-l+1;    if(l==r)    {        vl[rt]=vr[rt]=a[l];        mx1l[rt]=mx1r[rt]=mx2l[rt]=mx2r[rt]=mx2[rt]=1;        return ;    }    int mid=(l+r)>>1;    build(l,mid,rt<<1);    build(mid+1,r,rt<<1|1);    pushup(rt);}int main(){    int n;    scanf("%d",&n);    for(int i=1;i<=n;i++)        scanf("%d",&a[i]);    build(1,n,1);    int q;    scanf("%d",&q);    while(q--)    {        int a,b; ll d;        scanf("%d%d%lld",&a,&b,&d);        update(a,b,1,n,1,d);        printf("%d\n",mx2[1] );    }}