bzoj1558: [JSOI2009]等差数列

来源:互联网 发布:des密码算法 编辑:程序博客网 时间:2024/05/24 04:51

传送门
显然直接维护比较萎。
考虑差分。
然后一次操作就变成了一次区间加,两次单点加。
直接用线段树维护以下就可以了。
注意标记合并时不要手残

#include<cstdio>#include<cstdlib>#include<iostream>#include<cmath>#include<cstring>#include<algorithm>using namespace std;int n,q,l,r,a,b,s[100005];char fl[5];inline void re(int &x,int y){    if (y<x) x=y;}struct data{    int s[4],l,r;    data operator +(data y){        data c; c.l=l,c.r=y.r;        c.s[0]=s[2]+y.s[1]-(r==y.l);        re(c.s[0],s[0]+y.s[1]),re(c.s[0],s[2]+y.s[0]);        c.s[1]=s[3]+y.s[1]-(r==y.l);        re(c.s[1],s[1]+y.s[1]),re(c.s[1],s[3]+y.s[0]);        c.s[2]=s[2]+y.s[3]-(r==y.l);        re(c.s[2],s[2]+y.s[2]),re(c.s[2],s[0]+y.s[3]);        c.s[3]=s[3]+y.s[3]-(r==y.l);        re(c.s[3],s[3]+y.s[2]),re(c.s[3],s[1]+y.s[3]);        return c;    }};struct node{    int l,r,val;    data x;}t[400005];void pushdown(int x){    int l=x*2,r=x*2+1;    t[l].val+=t[x].val;    t[r].val+=t[x].val;    t[l].x.l+=t[x].val;    t[r].x.l+=t[x].val;    t[l].x.r+=t[x].val;    t[r].x.r+=t[x].val;    t[x].val=0;}void build(int x,int l,int r){    t[x].l=l; t[x].r=r;    if (l==r){        t[x].x.s[0]=0; t[x].x.l=t[x].x.r=s[l];        t[x].x.s[1]=t[x].x.s[2]=t[x].x.s[3]=1;        return;    }    int mid=(l+r)/2;    build(x*2,l,mid);    build(x*2+1,mid+1,r);    t[x].x=t[x*2].x+t[x*2+1].x;}data ask(int k,int x,int y){    int l=t[k].l,r=t[k].r,mid=(l+r)/2;    if (l==x&&r==y) return t[k].x;    if (t[k].val) pushdown(k);    if (y<=mid) return ask(k*2,x,y);    if (x>mid) return ask(k*2+1,x,y);    return ask(k*2,x,mid)+ask(k*2+1,mid+1,y);}void change(int k,int x,int y,int v){    int l=t[k].l,r=t[k].r,mid=(l+r)/2;    if (l==x&&r==y){        t[k].val+=v;        t[k].x.l+=v;        t[k].x.r+=v;        return;    }    if (t[k].val) pushdown(k);    if (y<=mid) change(k*2,x,y,v);    else if (x>mid) change(k*2+1,x,y,v);    else change(k*2,x,mid,v),change(k*2+1,mid+1,y,v);    t[k].x=t[k*2].x+t[k*2+1].x;}int main(){    scanf("%d",&n);    for (int i=1;i<=n;i++) scanf("%d",&s[i]);    for (int i=1;i<n;i++) s[i]=s[i+1]-s[i];    build(1,1,n-1);    scanf("%d",&q);    while (q--){        scanf("%s%d%d",fl,&l,&r);        if (fl[0]=='B'){            if (l==r) printf("1\n");            else printf("%d\n",ask(1,l,r-1).s[3]);        }        else{            scanf("%d%d",&a,&b);            if (l!=1) change(1,l-1,l-1,a);            if (l!=r) change(1,l,r-1,b);            if (r!=n) change(1,r,r,-(a+(r-l)*b));        }    }    return 0;}
0 0
原创粉丝点击