• BZOJ1558 等差数列


    题目链接:戳我

    实话实话,看了几篇题解真的没看懂,我觉得讲的都有问题。这里对于线段树维护的s写了一点我自己的理解。

    看到等差数列,我们考虑对数列做差,这样如果是等差数列,那么值应该相等。(比较容易维护,修改操作就变成了两个单点修改+一个区间修改,如果还是不理解的话可以参考一下代码)

    查询比较麻烦,有这样的情况需要考虑:

    举个例子——
    1 3 5 6 9 12
    它的差分数列为 2 2 1 3 3

    最佳选择肯定是(1,3,5)(6,9,12),ans=2
    但是我们纯看差分数列找相同的,ans=3

    为什么会多算呢?原因就在于差分数列为1的这个位置其实是两个等差数列拼合点,不需要考虑在内。

    所以我们设(s[0],s[1],s[2],s[3])分别表示当前区间中,不考虑两端、不考虑左端点、不考虑右端点、两端都考虑,形成等差数列的个数。

    两个区间合并的时候,左区间的右端点和右区间的左端点是至少要考虑一个的。因为如果都不考虑的娿,终究就遗漏了一个点了。两个都考虑时,如果中间差值相同,那么两个等差数列可以拼做一个,ans要-1.

    注意查询的时候区间写(l,r-1)qwqwqwq

    备注一下l,r记录的是左右端点的数值。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    using namespace std;
    #define MAXN 120000
    int v[MAXN],n;
    struct Data{int s[4],l,r;};
    struct Node
    {
        int l,r,v;
        Data x;
    }t[MAXN<<2];
    
    Data operator + (Data x,Data y)
    {
        Data cur;
        cur.l=x.l,cur.r=y.r;
    
        cur.s[0]=min(x.s[2]+y.s[0],x.s[0]+y.s[1]);
        cur.s[0]=min(cur.s[0],x.s[2]+y.s[1]-(y.l==x.r));
    
        cur.s[1]=min(x.s[1]+y.s[1],x.s[3]+y.s[0]);
        cur.s[1]=min(cur.s[1],x.s[3]+y.s[1]-(y.l==x.r));
    
        cur.s[2]=min(x.s[2]+y.s[2],x.s[0]+y.s[3]);
        cur.s[2]=min(cur.s[2],x.s[2]+y.s[3]-(y.l==x.r));
    
        cur.s[3]=min(x.s[3]+y.s[2],x.s[1]+y.s[3]);
        cur.s[3]=min(cur.s[3],x.s[3]+y.s[3]-(y.l==x.r));
    
        return cur;
    }
    
    inline int ls(int x){return x<<1;}
    
    inline int rs(int x){return x<<1|1;}
    
    inline void solve(int now,int k)
    {
        t[now].v+=k;
        t[now].x.l+=k;
        t[now].x.r+=k;
    }
    inline void pushdown(int now)
    {
        if(t[now].v)
        {
            solve(ls(now),t[now].v);
            solve(rs(now),t[now].v);
            t[now].v=0;
        }
    }
    
    inline void Build(int now,int l,int r)
    {
        t[now].l=l,t[now].r=r;
        if(l==r)
        {
            t[now].x.s[0]=0;
            t[now].x.s[1]=t[now].x.s[2]=t[now].x.s[3]=1;
            t[now].x.l=t[now].x.r=v[l];
            return;
        }
        int mid=(l+r)>>1;
        Build(ls(now),l,mid);
        Build(rs(now),mid+1,r);
        t[now].x=t[ls(now)].x+t[rs(now)].x;
    }
    
    
    inline Data Query(int now,int ll,int rr)
    {
        int l=t[now].l,r=t[now].r;
        if(l==ll&&r==rr) return t[now].x;
        pushdown(now);
        int mid=(l+r)>>1;
        if(rr<=mid) return Query(ls(now),ll,rr);
        if(mid<ll) return Query(rs(now),ll,rr);
        return Query(ls(now),ll,mid)+Query(rs(now),mid+1,rr);
    }
    
    inline void Modify(int now,int ll,int rr,int k)
    {
        int L=t[now].l,R=t[now].r;
        if(L==ll&&R==rr)
        {
            t[now].v+=k;
            t[now].x.l+=k,t[now].x.r+=k;
            return;
        }
        pushdown(now);
        int mid=(L+R)>>1;
        if(rr<=mid) Modify(ls(now),ll,rr,k);
        else if(mid<ll) Modify(rs(now),ll,rr,k);
        else
        {
            Modify(ls(now),ll,mid,k);
            Modify(rs(now),mid+1,rr,k);
        }
        t[now].x=t[ls(now)].x+t[rs(now)].x;
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        freopen("std.out","w",stdout);
        #endif 
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&v[i]);
        for(int i=1;i<n;i++) v[i]=v[i+1]-v[i];
        Build(1,1,n-1);
        int Q;
        scanf("%d",&Q);
        for(int i=1;i<=Q;i++)
        {
            char op[10];
            int s,t,a,b;
            scanf("%s",op);
            if(op[0]=='B')
            {
                scanf("%d%d",&s,&t);
                if(s==t) printf("1
    ");
                else printf("%d
    ",Query(1,s,t-1).s[3]);
            }
            else if(op[0]=='A')  
            {
                scanf("%d%d%d%d",&s,&t,&a,&b);
                if(s!=1) Modify(1,s-1,s-1,a); 
                if(s!=t) Modify(1,s,t-1,b);
                if(t!=n) Modify(1,t,t,-(t-s)*b-a); 
            }
        }
        return 0;
    }
    
  • 相关阅读:
    阿里云服务器ECS centos_7 安装jdk环境
    Spring Data Jpa 投影(Projection)的用法
    win10 docker 部署微服务
    centos 安装docker
    VMware 启动 虚拟机后一直黑屏
    VMware 新建虚拟机选择操作系统的时候提示,此主机不支持64位客户机操作系统,此系统无法运行
    mysql 表名全变小写的解决(windows)
    docker: Error response from daemon: driver failed programming external connectivity on endpoint jovial_morse (71d0315110605c3812f7255c7072f5d38512118a4635feaf84cdc170d3bee8d1): Error starting userland
    win10 docker部署springboot项目
    nginx failed (1113: No mapping for the Unicode character exists in the target multi-byte code page)
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10501139.html
Copyright © 2020-2023  润新知