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
",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));
}
}
}