[JSOI2009]等差数列

洛谷水过了,bzoj超时了

插入等差数列=》绝对是差分

至于能分成几个等差数列,浓浓的dp阴谋味;
好吧,正常的线段树收标记

维护

因为是差分=>且不用管数值
要跳过非连续等差数列首项

当前区间如果左右端点都不选有多少个等差数列 -> s[0]

当前区间如果只选左端点有多少个等差数列 -> s[1]

当前区间如果只选右端点有多少个等差数列 -> s[2]

当前区间如果左右端点都选有多少个等差数列 -> s[3]

#include<bits/stdc++.h>
#define re return
#define ll long long
#define lson rt<<1
#define rson rt<<1|1 
#define inc(i,l,r) for(int i=l;i<=r;++i)
#define dec(i,l,r) for(int i=l;i>=r;--i)
const int maxn=10e5+5;
using namespace std;
template<typename T>inline void rd(T&x)
{
	char c;bool f=0;
	while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
	x=c^48;
	while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
	if(f)x=-x;
}

int n,m,cnt,b[maxn];

struct data
{
	int l,r,s[4];	
	inline data operator+(data rs)const
	{
		data ans;
		ans.l=l;ans.r=rs.r;
		ans.s[0]=s[2]+rs.s[1]-(rs.l==r);
		ans.s[0]=min(ans.s[0],s[2]+rs.s[0]);ans.s[0]=min(ans.s[0],s[0]+rs.s[1]);
		ans.s[1]=s[3]+rs.s[1]-(rs.l==r);
		ans.s[1]=min(ans.s[1],s[1]+rs.s[1]);ans.s[1]=min(ans.s[1],s[3]+rs.s[0]);
		ans.s[2]=s[2]+rs.s[3]-(rs.l==r);
		ans.s[2]=min(ans.s[2],s[2]+rs.s[2]);ans.s[2]=min(ans.s[2],s[0]+rs.s[3]);
		ans.s[3]=s[3]+rs.s[3]-(rs.l==r);
		ans.s[3]=min(ans.s[3],s[1]+rs.s[3]);ans.s[3]=min(ans.s[3],s[3]+rs.s[2]);
		re ans;
	} 
};
struct node{
	int val;data x;
}tree[maxn<<2];
inline void build(int rt,int l,int r)
{
	if(l==r)
	{
		tree[rt].x.s[1]=tree[rt].x.s[2]=tree[rt].x.s[3]=1;
		tree[rt].x.l=tree[rt].x.r=b[l+1]-b[l];
		tree[rt].val=tree[rt].x.s[0]=0;
		re ;
	}
	tree[rt].val=0;
	int mid=(l+r)>>1;
	build(lson,l,mid);
	build(rson,mid+1,r); 
	tree[rt].x=tree[lson].x+tree[rson].x;
}

inline void pushdown(int rt)
{
	tree[lson].val+=tree[rt].val;tree[rson].val+=tree[rt].val;
	tree[lson].x.l+=tree[rt].val;tree[rson].x.l+=tree[rt].val;
	tree[lson].x.r+=tree[rt].val;tree[rson].x.r+=tree[rt].val;
	tree[rt].val=0;
	re;
}

inline void add(int rt,int l,int r,int x,int y,int num)
{
	if(x<=l&&r<=y)
	{
		tree[rt].val+=num;
		tree[rt].x.l+=num;
		tree[rt].x.r+=num;
		re ;
	}
	if(tree[rt].val)pushdown(rt);
	int mid=(l+r)>>1;
	if(x<=mid)add(lson,l,mid,x,y,num);
	if(y>mid)add(rson,mid+1,r,x,y,num);
	tree[rt].x=tree[lson].x+tree[rson].x;
}

inline data query(int rt,int l,int r,int x,int y)
{
	if(x<=l&&r<=y)re tree[rt].x;
	if(tree[rt].val)pushdown(rt);
	int mid=(l+r)>>1;
	data v;
	if(y<=mid)v=query(lson,l,mid,x,y);
	else if(mid<x)v=query(rson,mid+1,r,x,y);
	else v=query(lson,l,mid,x,y)+query(rson,mid+1,r,x,y);
	tree[rt].x=tree[lson].x+tree[rson].x;
	re v;
	
}
int main()
{
//	freopen("in.txt","r",stdin);
	rd(n);
	inc(i,1,n)
	rd(b[i]);
	build(1,1,n-1);
	char c;
	int q,s,t,a,b;
	rd(q);
	inc(i,1,q)
	{
		while((c=getchar())!='A'&&c!='B');
		if(c=='A')
		{
			rd(s),rd(t),rd(a),rd(b);
			if(s!=1)add(1,1,n-1,s-1,s-1,a);
			if(t!=n)add(1,1,n-1,t,t,-(a+b*(t-s)));
			if(s!=t)add(1,1,n-1,s,t-1,b);
		}
		else {
			rd(s),rd(t);
			if(s==t)
			{
				printf("1\n");
				continue;
			}
			else
			{
				data v=query(1,1,n-1,s,t-1);
				printf("%d\n",v.s[3]);
			}
		}
	}
	re 0;
}
posted @ 2019-07-29 18:56  凉如水  阅读(264)  评论(0编辑  收藏  举报