题面

首先感谢这篇题解,是思路来源


看到等差数列,就会想到差分,又有区间加,很容易想到线段树维护差分。再注意点细节,\(A\)操作完美解决
然后就是爆炸恶心的\(B\)操作,之前看一堆题解的解释都不怎么明白,就自己脑补+看上面那篇题解乱搞出了个相对合理点的解释……
用\(0/1/2/3\)分别表示一个差分区间统计答案时,是否跨越原区间左右端点。\(s[0/1/2/3]\)分别表示每个状态的最少可以划分出来的等差数列个数。
合并方式如下:

/*定义差分b[i]=a[i+1]-a[i]
假设要查询区间[S,T],对应到差分数组实际查询的是区间[S,T-1]
所以一个节点如果在差分数组上维护的区间是[a,b],在原数组上维护的实际上是区间[a,b+1]*/

//s[0]表示原数组中区间为(S,T)的答案
//s[1]表示原数组中区间为(S,T]的答案
//s[2]表示原数组中区间为[S,T)的答案
//s[3]表示原数组中区间为[S,T]的答案

s[0]= min(s[1]+ s[2]- ( vr==Y.vl), min(s[0]+ s[2], s[1]+s[0] ) );

s[1]= min(s[1]+ Y.s[3]- ( vr==Y.vl), min(s[1]+ s[1], s[0]+s[3] ) );

s[2]= min(s[3]+ s[2]- ( vr==Y.vl), min(s[2]+ s[2], s[3]+s[0] ) );

s[3]= min(s[3]+ s[3]- ( vr==Y.vl), min(s[3]+ s[1], s[2]+s[3] ) );

输出时直接输出\(s[3]\)就OK了

\(p.s.\) \(n==1\)时不用建树,否则\(RE\)

代码:

#include <bits/stdc++.h>
#define N 100005
using namespace std;

int a[N],n;

#define bas int l,int r,int o
#define lson l,mid,o<<1
#define rson mid+1,r,o<<1|1

struct node{
    int s[4];
    long long vl,vr;
    node operator +(const node &Y)const{
        node Z;
        Z.vl=vl,Z.vr=Y.vr;
        Z.s[0]= min(s[1]+ Y.s[2]- ( vr==Y.vl), min(s[0]+ Y.s[2], s[1]+Y.s[0] ) );
        Z.s[1]= min(s[1]+ Y.s[3]- ( vr==Y.vl), min(s[1]+ Y.s[1], s[0]+Y.s[3] ) );
        Z.s[2]= min(s[3]+ Y.s[2]- ( vr==Y.vl), min(s[2]+ Y.s[2], s[3]+Y.s[0] ) );
        Z.s[3]= min(s[3]+ Y.s[3]- ( vr==Y.vl), min(s[3]+ Y.s[1], s[2]+Y.s[3] ) );
        return Z;
    }
};
struct qwq{
    long long tag[N<<2];
    node t[N<<2];
    void pushdown(int o){
        t[o<<1].vl+= tag[o], t[o<<1].vr+= tag[o];
        t[o<<1|1].vl+= tag[o], t[o<<1|1].vr+= tag[o];
        tag[o<<1]+= tag[o], tag[o<<1|1]+= tag[o];
        tag[o]=0;
    }
    void build(bas){
        tag[o]=0;
        if(l==r){
            t[o].vl= t[o].vr= a[l];
            t[o].s[1]= t[o].s[2]= t[o].s[3]= 1, t[o].s[0]=0;//两个数时和一个数时等差数列数量都是1
            return;
        }
        int mid=(l+r)>>1;
        build(lson),build(rson);
        t[o]= t[o<<1]+ t[o<<1|1];
    }
    void update(bas,int L,int R,long long x){
        if(L<=l && r<=R){
            t[o].vl+= x, t[o].vr+= x;
            tag[o]+= x;
            return;
        }
        if(tag[o]) pushdown(o);
        int mid= (l+r)>>1;
        if(L<= mid) update(lson,L,R,x);
        if(R> mid) update(rson,L,R,x);
        t[o]= t[o<<1]+ t[o<<1|1];
    }
    node query(bas,int L,int R){
        if(L<= l && r<= R) return t[o];
        if(tag[o]) pushdown(o);
        int mid= (l+r)>>1;
        if(R<=mid) return query(lson,L,R);
        else{
            if(L>mid) return query(rson,L,R);
            else return query(lson,L,R)+query(rson,L,R);
        }
    }
}T;

int main(){
    int q,s,t,c,d,ans,i;
    char op;
    scanf("%d",&n);
    for(i=1;i<=n;++i) scanf("%d",&a[i]);
    for(i=1;i<n;++i) a[i]=a[i+1]-a[i];
    if(n!=1) T.build(1,n-1,1);
    scanf("%d",&q);
    while(q--){
        scanf("\n%c",&op);
        if(op=='A'){
            scanf("%d%d%d%d",&s,&t,&c,&d);
            if(s!=1) T.update(1,n-1,1,s-1,s-1,c);
            if(t!=n) T.update(1,n-1,1,t,t,1ll*d*s-1ll*d*t-c);
            if(s!=t) T.update(1,n-1,1,s,t-1,d);
        } else{
            scanf("%d%d",&s,&t);
            if(t- s+ 1==1) ans=1;
            else{
                node res=T.query(1,n-1,1,s,t-1);
                ans=min((t-s+2)/2,res.s[3]);
            }
            printf("%d\n",ans);
        }
    }
}

洛谷P4243/bzoj1558 [JSOI2009]等差数列(线段树维护差分+爆炸恶心的合并)的更多相关文章

  1. 洛谷 P4747 [CERC2017]Intrinsic Interval 线段树维护连续区间

    题目描述 题目传送门 分析 考虑对于 \([l,r]\),如何求出包住它的长度最短的好区间 做法就是用一个指针从 \(r\) 向右扫,每次查询以当前指针为右端点的最短的能包住 \([l,r]\) 的好 ...

  2. 洛谷 P3373 【模板】线段树 2

    洛谷 P3373 [模板]线段树 2 洛谷传送门 题目描述 如题,已知一个数列,你需要进行下面三种操作: 将某区间每一个数乘上 xx 将某区间每一个数加上 xx 求出某区间每一个数的和 输入格式 第一 ...

  3. BZOJ.1558.[JSOI2009]等差数列(线段树 差分)

    BZOJ 洛谷 首先可以把原序列\(A_i\)转化成差分序列\(B_i\)去做. 这样对于区间加一个等差数列\((l,r,a_0,d)\),就可以转化为\(B_{l-1}\)+=\(a_0\),\(B ...

  4. 洛谷P2221 [HAOI2012]高速公路(线段树+概率期望)

    传送门 首先,答案等于$$ans=\sum_{i=l}^r\sum_{j=i}^r\frac{sum(i,j)}{C_{r-l+1}^2}$$ 也就是说所有情况的和除以总的情况数 因为这是一条链,我们 ...

  5. 洛谷3822 [NOI2017] 整数 【线段树】【位运算】

    题目分析: 首先这题的询问和位(bit)有关,不难想到是用线段树维护位运算. 现在我们压32位再来看这道题. 对于一个加法操作,它的添加位置可以得到,剩下的就是做不超过32的位移.这样根据压位的理论. ...

  6. 洛谷P4425 [HNOI/AHOI2018]转盘(线段树)

    题意 题目链接 Sol 首先猜一个结论:对于每次询问,枚举一个起点然后不断等到某个点出现时才走到下一个点一定是最优的. 证明不会,考场上拍了3w组没错应该就是对的吧... 首先把数组倍长一下方便枚举起 ...

  7. 洛谷P4425 转盘 [HNOI/AHOI2018] 线段树+单调栈

    正解:线段树+单调栈 解题报告: 传送门! 1551又是一道灵巧连题意都麻油看懂的题,,,,所以先解释一下题意好了,,,, 给定一个n元环 可以从0时刻开始从任一位置出发 每次可以选择向前走一步或者在 ...

  8. 洛谷 P3924 康娜的线段树 解题报告

    P3924 康娜的线段树 题目描述 小林是个程序媛,不可避免地康娜对这种人类的"魔法"产生了浓厚的兴趣,于是小林开始教她\(OI\). 今天康娜学习了一种叫做线段树的神奇魔法,这种 ...

  9. 【洛谷 P3834】 可持久化线段树1(主席树)

    题目链接 主席树=可持久化权值线段树. 如果你不会可持久化线段树,请右转 如果你不会权值线段树,请自行脑补,就是线段树维护值域里有多少个数出现. 可持久化线段树是支持查询历史版本的. 我们对每个数都进 ...

随机推荐

  1. Linux Centos 迁移Mysql 数据位置

    Linux Centos 迁移Mysql 数据位置 由于业务量增加导致安装在系统盘(20G)磁盘空间被占满了, 现在进行数据库的迁移. Mysql 是通过 yum 安装的. Centos6.5Mysq ...

  2. PostgreSQL 安装了contrib 之后 登录失败的问题

    1. 自己之前只是安装了 pg 10.6 2. 开发同事 需要用到 一个extensions 叫做 uuid-ossp 3. 执行报错  详情见昨天的blog 4. 然后执行了升级操作 结果 pg10 ...

  3. python学习笔记(9)--函数

    函数定义: def <函数名>(<参数(0个或多个)>): 函数体 return <返回值> 参数有非可选参数,和可选参数,可选参数放在参数列表的最后,可以为可选参 ...

  4. Centso7 简单优化(阿里云服务器)

    ##.下载常用包 # yum -y install wget net-tools screen lsof tcpdump nc mtr openssl-devel vim bash-completio ...

  5. django mysql数据库使用自己的User

    由于我需要的User模型与django自带的User有所不同,所以需要定义自己的User Model,这里记录一下方法,适用于django 1.5+. 因为使用自己的后台,放弃django的管理后台, ...

  6. 面对AI

    面对AI,我们应该怎么做? 李开复博士的一段话: 1. 我们应该具有战略性思维,并以人工智能无法取代的工作为目标.我们应该致力于终身学习,更新我们的技能,了解新趋势,并寻找新机遇. 2. 我们应该鼓励 ...

  7. git reset 版本回退的三种用法总结

    git reset (–mixed) HEAD~1 回退一个版本,且会将暂存区的内容和本地已提交的内容全部恢复到未暂存的状态,不影响原来本地文件(未提交的也不受影响) git reset –soft ...

  8. 2.ansible-playbook基本参数

    ansible-playbook的参数--force-handlers run handlers even if a task fails 强制执行handler--list-tags list al ...

  9. Mayor's posters(线段树+离散化)

    这道题最关键的点就在离散化吧. 假如有三张海报[1, 10] [10, 13][15,  20] 仅仅三个区间就得占用到20了. 但是离散化后就可以是[1, 2] [2, 3] [4, 5] n到1e ...

  10. Nginx 多核cpu负载均衡

    L:122 查看Linux CPU 缓存大小 cat /sys/devices/system/cpu/cpu1/cache/index0/size //指令缓存 cat /sys/devices/sy ...