• 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
    ",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));
    		}
    	}
    }
    
  • 相关阅读:
    杭电2095--find your present (2) (异或)
    南阳168--房间安排(区间覆盖)
    南阳954--N!(数学)
    南阳--69(数的长度)
    杭电--N!(大数)
    杭电1005--Number Sequence
    杭电1108--最小公倍数
    动态规划:最长上升子序列(二分算法 nlogn)
    动态规划:最长上升子序列之基础(经典算法 n^2)
    vector函数用法
  • 原文地址:https://www.cnblogs.com/victorique/p/10384402.html
Copyright © 2020-2023  润新知