BZOJ 1558: [JSOI2009]等差数列

差分,转化为两个单点修改和一个区间修改

维护00,01,10,11表示左右端点取或不取的最小值

线段树即可

#include<cstdio>
#include<algorithm>
using namespace std;
int n,tag[550005],a[100005];
char s[15];
struct node{
	int F00,F01,F10,F11,l,r;
}tree[550005];
node merge(node L,node R){
	node ans;
	ans.l=L.l,ans.r=R.r;
	int val=(L.r==R.l);
	ans.F00=L.F01+R.F10-val;
	ans.F00=min(ans.F00,L.F00+R.F10);
	ans.F00=min(ans.F00,L.F01+R.F00);
	
	ans.F01=L.F01+R.F11-val;
	ans.F01=min(ans.F01,L.F00+R.F11);
	ans.F01=min(ans.F01,L.F01+R.F01);
	
	ans.F10=L.F11+R.F10-val;
	ans.F10=min(ans.F10,L.F10+R.F10);
	ans.F10=min(ans.F10,L.F11+R.F00);
	
	ans.F11=L.F11+R.F11-val;
	ans.F11=min(ans.F11,L.F10+R.F11);
	ans.F11=min(ans.F11,L.F11+R.F01);
	return ans;
}
void push_down(int t){
	tag[t<<1]+=tag[t],tag[t<<1|1]+=tag[t];
	tree[t<<1].l+=tag[t],tree[t<<1].r+=tag[t];
	tree[t<<1|1].l+=tag[t],tree[t<<1|1].r+=tag[t];
	tag[t]=0;
}
void build(int t,int l,int r){
	if (l==r){
		int val=a[l+1]-a[l];
		tree[t]=(node){0,1,1,1,val,val};
		return;
	}
	int mid=(l+r)>>1;
	build(t<<1,l,mid);
	build(t<<1|1,mid+1,r);
	tree[t]=merge(tree[t<<1],tree[t<<1|1]);
}
void modify(int t,int l,int r,int x,int y,int w){
	if (l>y || r<x) return;
	if (l>=x && r<=y){
		tree[t].l+=w,tree[t].r+=w;
		tag[t]+=w;
		return;
	}
	if (tag[t]) push_down(t);
	int mid=(l+r)>>1;
	modify(t<<1,l,mid,x,y,w);
	modify(t<<1|1,mid+1,r,x,y,w);
	tree[t]=merge(tree[t<<1],tree[t<<1|1]);
}
node query(int t,int l,int r,int x,int y){
	if (l==x && r==y) return tree[t];
	if (tag[t]) push_down(t);
	int mid=(l+r)>>1;
	if (y<=mid) return query(t<<1,l,mid,x,y);
	if (x>mid) return query(t<<1|1,mid+1,r,x,y);
	return merge(query(t<<1,l,mid,x,mid),query(t<<1|1,mid+1,r,mid+1,y));
}
int main(){
	scanf("%d",&n);
	for (int i=1; i<=n; i++) scanf("%d",&a[i]);
	build(1,1,n-1);
	int q;
	scanf("%d",&q);
	while (q--){
		scanf("%s",s);
		if (s[0]=='A'){
			int s,t,a,b;
			scanf("%d%d%d%d",&s,&t,&a,&b);
			if (s-1) modify(1,1,n-1,s-1,s-1,a);
			if (s!=t) modify(1,1,n-1,s,t-1,b);
			if (t<n) modify(1,1,n-1,t,t,-(t-s)*b-a);
		}
		else if (s[0]=='B'){
			int s,t;
			scanf("%d%d",&s,&t);
			if (s==t) printf("1\n");
			else printf("%d\n",query(1,1,n-1,s,t-1).F11);
		}
	}
	return 0;
}

  

posted @ 2018-11-01 20:24  ~Silent  阅读(155)  评论(0编辑  收藏  举报
Live2D