其他分享
首页 > 其他分享> > BZOJ1558: [JSOI2009]等差数列

BZOJ1558: [JSOI2009]等差数列

作者:互联网

BZOJ1558: [JSOI2009]等差数列


题目描述

传送门

题目分析

等差数列的题么,先差分一下,然后就变成了一个数列上,求\([L,R]\)区间内连续相同的段数了。很相似的是[SDOI2011]染色这道题,但是由于我们这个线段树存的是差分后的数组,所以需要考虑一个数是否作为一个分段的头和尾造成的影响。这个也是可以使用线段树快速维护的。

是代码呢

#include <bits/stdc++.h>
using namespace std;
#define ls rt<<1
#define rs rt<<1|1
#define mid ((l+r)>>1)
const int MAXN=1e5+7;
#define ll long long
int a[MAXN],n,q;
char opt[12];
struct po{
    int s[5],l,r;
}st[MAXN<<2];
po operator +(po x,po y){
        po c;c.l=x.l;c.r=y.r;
        c.s[0]=x.s[2]+y.s[1]-(x.r==y.l);
        c.s[0]=min(c.s[0],x.s[0]+y.s[1]);
        c.s[0]=min(c.s[0],x.s[2]+y.s[0]);
        c.s[1]=x.s[3]+y.s[1]-(x.r==y.l);
        c.s[1]=min(c.s[1],x.s[1]+y.s[1]);
        c.s[1]=min(c.s[1],x.s[3]+y.s[0]);
        c.s[2]=x.s[2]+y.s[3]-(x.r==y.l);
        c.s[2]=min(c.s[2],x.s[2]+y.s[2]);
        c.s[2]=min(c.s[2],x.s[0]+y.s[3]);
        c.s[3]=x.s[3]+y.s[3]-(x.r==y.l);
        c.s[3]=min(c.s[3],x.s[1]+y.s[3]);
        c.s[3]=min(c.s[3],x.s[3]+y.s[2]);
        return c;
    }
inline void clear(po x){x.s[0]=x.s[1]=x.s[2]=x.s[3]=x.l=x.r=0;}
int val[MAXN<<2];
inline void pushup(int rt){st[rt]=st[ls]+st[rs];}
inline void pushdown(int l,int r,int rt)
{
    if(val[rt]){
        val[ls]+=val[rt];val[rs]+=val[rt];
        st[ls].l+=val[rt];st[ls].r+=val[rt];
        st[rs].l+=val[rt];st[rs].r+=val[rt];
        val[rt]=0;
    }
}
inline void build(int l,int r,int rt)
{
    if(l==r){
        st[rt].s[1]=st[rt].s[2]=st[rt].s[3]=1;
        st[rt].l=st[rt].r=a[l];
        return;
    }
    build(l,mid,ls);build(mid+1,r,rs);
    pushup(rt);
}
inline void change(int L,int R,int l,int r,int rt,int k)
{
    if(L<=l&&r<=R){
        val[rt]+=k;
        st[rt].l+=k;st[rt].r+=k;
        return;
    }
    pushdown(l,r,rt);
    if(L<=mid) change(L,R,l,mid,ls,k);
    if(R>mid) change(L,R,mid+1,r,rs,k);
    pushup(rt);
}
inline po query(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R) return st[rt];
    pushdown(l,r,rt);
    if(R<=mid) return query(L,R,l,mid,ls);
    if(L>mid) return query(L,R,mid+1,r,rs);
    return query(L,R,l,mid,ls)+query(L,R,mid+1,r,rs);
}
inline int read()
{
    int x=0,c=1;
    char ch=' ';
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    while(ch=='-')c*=-1,ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*c;
}
int main()
{
    n=read();
    for(int i=1;i<=n;i++) a[i]=read();
    for(int i=1;i<n;i++) a[i]=a[i+1]-a[i];
    n--;
    build(1,n,1);
    q=read();
    while(q--){
        scanf("%s",opt);
        int l=read(),r=read();
        if(opt[0]=='B'){
            if(l==r) puts("1");
            else{
                int d=query(l,r-1,1,n,1).s[3];
                printf("%d\n",d);
            }
        } else {
            int x=read(),y=read();
            if(l!=1) change(l-1,l-1,1,n,1,x);
            if(l!=r) change(l,r-1,1,n,1,y);
            if(r!=n+1) change(r,r,1,n,1,-(x+(r-l)*y));
        }
    }
}

标签:rt,ch,int,JSOI2009,mid,BZOJ1558,while,query,等差数列
来源: https://www.cnblogs.com/victorique/p/10384402.html