zoukankan      html  css  js  c++  java
  • 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
    ");
    			else printf("%d
    ",query(1,1,n-1,s,t-1).F11);
    		}
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    VUE常用传值方式、父传子、子传父、非父子组件传值
    ios10中禁止用户缩放页面
    TCP MSS
    C++11 之 override
    unordered_set
    c++Lambda
    QUIC实现代码分析
    C++11新特性之十:enable_shared_from_this
    c++11 atomic
    How to Write a QUIC Endpoint Program
  • 原文地址:https://www.cnblogs.com/silenty/p/9892255.html
Copyright © 2011-2022 走看看