zoukankan      html  css  js  c++  java
  • [bzoj1558][JSOI2009]等差数列

    题目:给定n个数,m个操作,每次给一段区间加一个等差数列或者询问一段区间至少要用多少个等差数列来表示。$n,mleqslant 10^{5}$

    题解:老套路,维护差分数组,修改操作变成了两个单点加和一个区间加。然后我们用线段树维护,合并答案的时候复杂一点,s[0/1][0/1]表示左右端点取不取的答案就行啦。

    #include<iostream>
    #include<cstdio>
    #define MN 100000
    using namespace std;
    inline int read()
    {
        int x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    
    int n,q,s[MN+5];
    char op[4];
    
    inline void re(int&x,int y){if(y<x) x=y;}
    
    struct data
    {
        int s[4],l,r;
        data operator + (data y)
        {
            data c;c.l=l;c.r=y.r;
            c.s[0]=s[2]+y.s[1]-(r==y.l);
            re(c.s[0],s[0]+y.s[1]);re(c.s[0],s[2]+y.s[0]);
            c.s[1]=s[3]+y.s[1]-(r==y.l);
            re(c.s[1],s[1]+y.s[1]);re(c.s[1],s[3]+y.s[0]);
            c.s[2]=s[2]+y.s[3]-(r==y.l);
            re(c.s[2],s[2]+y.s[2]);re(c.s[2],s[0]+y.s[3]);
            c.s[3]=s[3]+y.s[3]-(r==y.l);
            re(c.s[3],s[3]+y.s[2]);re(c.s[3],s[1]+y.s[3]); 
            return c;
        }
    }; 
    struct node{
        int l,r,val;data x;
    }T[MN*4+5];
    
    void pushdown(int x)
    {
        int l=x<<1,r=x<<1|1;
        T[l].val+=T[x].val;T[r].val+=T[x].val;
        T[l].x.l+=T[x].val;T[l].x.r+=T[x].val;
        T[r].x.l+=T[x].val;T[r].x.r+=T[x].val;
        T[x].val=0;
    }
    
    void build(int x,int l,int r)
    {
        if((T[x].l=l)==(T[x].r=r)) 
        {    
            T[x].x.s[0]=0;T[x].x.l=T[x].x.r=s[l];
            T[x].x.s[1]=T[x].x.s[3]=T[x].x.s[2]=1;
            return;
        }
        int mid=l+r>>1;
        build(x<<1,l,mid);build(x<<1|1,mid+1,r);
        T[x].x=T[x<<1].x+T[x<<1|1].x;
    }
    
    data query(int x,int l,int r)
    {
        //cout<<"query"<<x<<" "<<l<<" "<<r<<" "<<T[x].l<<" "<<T[x].r<<endl;
        if(T[x].l==l&&T[x].r==r) return T[x].x;
        if(T[x].val) pushdown(x);
        int mid=T[x].l+T[x].r>>1;
        if(r<=mid) return query(x<<1,l,r);
        else if(l>mid) return query(x<<1|1,l,r);
        else return query(x<<1,l,mid)+query(x<<1|1,mid+1,r);
    }
    
    void modify(int x,int l,int r,int ad)
    {
        if(T[x].l==l&&T[x].r==r)
        {
            T[x].val+=ad;T[x].x.l+=ad;T[x].x.r+=ad;
            return;
        }
        if(T[x].val) pushdown(x);
        int mid=T[x].l+T[x].r>>1;
        if(r<=mid) modify(x<<1,l,r,ad);
        else if(l>mid) modify(x<<1|1,l,r,ad);
        else modify(x<<1,l,mid,ad),modify(x<<1|1,mid+1,r,ad); 
        T[x].x=T[x<<1].x+T[x<<1|1].x;
    }
    
    int main()
    {
        n=read();
        for(int i=1;i<=n;i++) s[i]=read();    
        for(int i=1;i<n;i++) s[i]=s[i+1]-s[i];
        build(1,1,n-1);
        for(q=read();q;q--)
        {
            scanf("%s",op);int l=read(),r=read();
            if(op[0]=='B') l==r?puts("1"):printf("%d
    ",query(1,l,r-1).s[3]);
            else
            {
                int a=read(),b=read();
                if(l!=1) modify(1,l-1,l-1,a);
                if(l!=r) modify(1,l,r-1,b);
                if(r!=n) modify(1,r,r,-(a+(r-l)*b));    
            }
        }
        return 0;
    }
  • 相关阅读:
    165. Compare Version Numbers
    164. Maximum Gap
    3、桶排序
    162. Find Peak Element
    160. Intersection of Two Linked Lists
    155. Min Stack
    154. Find Minimum in Rotated Sorted Array II
    153. Find Minimum in Rotated Sorted Array
    Linux/Unix系统编程手册 第二章:基本概念
    Linux/Unix系统编程手册 第一章:历史和标准
  • 原文地址:https://www.cnblogs.com/FallDream/p/bzoj1558.html
Copyright © 2011-2022 走看看