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));
		}
	}
}
posted @ 2019-02-15 16:36  ~victorique~  阅读(118)  评论(0编辑  收藏  举报
Live2D