BZOJ

洛谷

首先可以把原序列\(A_i\)转化成差分序列\(B_i\)去做。

这样对于区间加一个等差数列\((l,r,a_0,d)\),就可以转化为\(B_{l-1}\)+=\(a_0\),\(B_r\)-=\((r-l)*d+a_0\),\(B_{l...r-1}\)+=\(d\)。

对于查询,似乎只需要求区间\(b_i\)的连续段个数?

并不是,比如:

\(A:\ 0\ 1\ 3\ 6\ 10\\B:\ \ \ 1\ 2\ 3\ 4\)

答案是\(3\)而不是\(4\),我们可以这样划分:\(\{0,1\},\{3,6\},\{10\}\),或是\(\{0,1\},\{3\},\{6,10\}\)等等,得到三个等差数列。

为什么会不是\(4\)呢,除了两个数也是一个等差数列外,如果我们选择了差分序列中的\(1,4\),也就是选\(\{0,1\},\{6,10\}\)划分成两个等差数列,那\(A_3=3\)是属于\(B_2=2\)还是\(B_3=3\)呢?

问题其实在于,区间中间那个数只能属于左右等差数列中的一个(或是相等的时候可以把两个等差数列连起来)。

然而网上好多题解都没有明说这件事啊?只看到两三篇是这个意思的(这个这个yyb的其实也是吧),其它题解只是写了下\(s\)的定义,一点关于"左右端点选不选"是什么的解释都没有(当然也许只是我不能理解)。

当然只是个人理解咯。(表示我一共想了三种理解哪种都能和代码对应上,但前两种并不能说过去)

然后,小区间内部的答案在合并成大区间时是不会变的,要考虑的只是端点属于哪个区间的问题。

所以可以用线段树维护,令\(L,R\)表示当前区间的\(B_l,B_r\),\(s_0,s_1,s_2,s_3\)分别表示,左右端点都不属于这个区间(不与这个区间中的数构成等差数列)时的答案, 左端点属于而右端点不属于这个区间的答案,右端点属于而左端点不属于这个区间的答案,左右端点都属于这个区间的答案。

有这些就可以合并区间了,这里就可以见代码了。

询问的答案,就是询问区间合并后的\(s_3\)。

因为是在差分后的序列上做,询问\([l,r]\)是查询\([l,r-1]\),还要注意边界问题。

复杂度\(O(q\log n)\)。

//12460kb	2476ms
#include <cstdio>
#include <cctype>
#include <algorithm>
//#define gc() getchar()
#define MAXIN 300000
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
typedef long long LL;
const int N=1e5+5; int A[N];
char IN[MAXIN],*SS=IN,*TT=IN;
struct Node
{
int L,R,s0,s1,s2,s3;//s0:(l,r) 左右都不属于 s1:[l,r) s2:(l,r] s3:[l,r]
inline Node operator +(const Node &b)
{
Node c;
c.L=L, c.R=b.R; int v=R==b.L;
c.s0=std::min(s2+b.s1-v, std::min(s0+b.s1, s2+b.s0));
c.s1=std::min(s3+b.s1-v, std::min(s3+b.s0, s1+b.s1));
c.s2=std::min(s2+b.s3-v, std::min(s0+b.s3, s2+b.s2));
c.s3=std::min(s3+b.s3-v, std::min(s1+b.s3, s3+b.s2));
return c;
}
};
struct Segment_Tree
{
#define ls rt<<1
#define rs rt<<1|1
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define S N<<2
int tag[S];
Node t[S];
#undef S
#define Upd(x,v) t[x].L+=v, t[x].R+=v, tag[x]+=v
#define Update(rt) t[rt]=t[ls]+t[rs]
inline void PushDown(int rt)
{
Upd(ls,tag[rt]), Upd(rs,tag[rt]), tag[rt]=0;
}
void Build(int l,int r,int rt)
{
if(l==r)
{
t[rt]=(Node){A[l],A[l],0,1,1,1};
return;
}
int m=l+r>>1;
Build(lson), Build(rson), Update(rt);
}
void Modify(int l,int r,int rt,int L,int R,int v)
{
if(L<=l && r<=R) {Upd(rt,v); return;}
if(tag[rt]) PushDown(rt);
int m=l+r>>1;
if(L<=m) Modify(lson,L,R,v);
if(m<R) Modify(rson,L,R,v);
Update(rt);
}
void ModifyP(int l,int r,int rt,int p,int v)
{
if(l==r) {Upd(rt,v); return;}
if(tag[rt]) PushDown(rt);
int m=l+r>>1;
p<=m ? ModifyP(lson,p,v) : ModifyP(rson,p,v);
Update(rt);
}
Node Query(int l,int r,int rt,int L,int R)
{
if(L<=l && r<=R) return t[rt];
if(tag[rt]) PushDown(rt);
int m=l+r>>1;
if(L<=m)
if(m<R) return Query(lson,L,R)+Query(rson,L,R);
else return Query(lson,L,R);
return Query(rson,L,R);
}
}T; inline int read()
{
int now=0,f=1;register char c=gc();
for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now*f;
}
inline char GetOpt()
{
register char c=gc();
while(c!='A'&&c!='B') c=gc();
return c;
} int main()
{
int n=read();
for(int i=1; i<=n; ++i) A[i]=read();
if(n==1)
{
for(int Q=read(); Q--; )
if(GetOpt()=='B') puts("1");
return 0;
}
--n;
for(int i=1; i<=n; ++i) A[i]=A[i+1]-A[i];
T.Build(1,n,1);
for(int Q=read(); Q--; )
switch(GetOpt())
{
case 'A':
{
int l=read(),r=read(),a=read(),d=read();
if(l<r) T.Modify(1,n,1,l,r-1,d);
if(l>1) T.ModifyP(1,n,1,l-1,a);
if(r<=n) T.ModifyP(1,n,1,r,(l-r)*d-a);//r!=n!
break;
}
case 'B':
{
int l=read(),r=read();
if(l!=r) printf("%d\n",T.Query(1,n,1,l,r-1).s3);
else puts("1");
break;
}
}
return 0;
}

BZOJ.1558.[JSOI2009]等差数列(线段树 差分)的更多相关文章

  1. bzoj 1558: [JSOI2009]等差数列

    Description Solution 把原数组变为差分数组,然后剩下的就十分显然了 区间查询用线段树维护 修改操作就是区间加法和两个单点修改 一个等差数列实际上就是 开头一个数字+数值相等的一段 ...

  2. Bzoj 2752 高速公路 (期望,线段树)

    Bzoj 2752 高速公路 (期望,线段树) 题目链接 这道题显然求边,因为题目是一条链,所以直接采用把边编上号.看成序列即可 \(1\)与\(2\)号点的边连得是. 编号为\(1\)的点.查询的时 ...

  3. D - 小Z的加油店 线段树+差分+GCD

    D - 小Z的加油店 HYSBZ - 5028   这个题目是一个线段树+差分+GCD 推荐一个差分的博客:https://www.cnblogs.com/cjoierljl/p/8728110.ht ...

  4. bzoj 4373 算术天才⑨与等差数列——线段树+set

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4373 能形成公差为k的等差数列的条件:mx-mn=k*(r-l) && 差分 ...

  5. BZOJ 4373 算术天才⑨与等差数列 线段树+set(恶心死我了)

    mdzz,这道题重构了4遍,花了一个晚上... 满足等差数列的条件: 1. 假设min是区间最小值,max是区间最大值,那么 max-min+k(r−l) 2. 区间相邻两个数之差的绝对值的gcd=k ...

  6. BZOJ 4373算术天才⑨与等差数列(线段树)

    题意:给你一个长度为n的序列,有m个操作,写一个程序支持以下两个操作: 1. 修改一个值 2. 给出三个数l,r,k, 询问:如果把区间[l,r]的数从小到大排序,能否形成公差为k的等差数列. n,m ...

  7. BZOJ 4422 Cow Confinement (线段树、DP、扫描线、差分)

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=4422 我真服了..这题我能调一天半,最后还是对拍拍出来的...脑子还是有病啊 题解: ...

  8. 【BZOJ4373】算术天才⑨与等差数列 线段树+set

    [BZOJ4373]算术天才⑨与等差数列 Description 算术天才⑨非常喜欢和等差数列玩耍.有一天,他给了你一个长度为n的序列,其中第i个数为a[i].他想考考你,每次他会给出询问l,r,k, ...

  9. 洛谷P1438 无聊的数列 (线段树+差分)

    变了个花样,在l~r区间加上一个等差数列,等差数列的显著特点就是公差d,我们容易想到用线段树维护差分数组,在l位置加上k,在l+1~r位置加上d,最后在r+1位置减去k+(l-r)*d,这样就是在差分 ...

随机推荐

  1. Java基本语法(一)

    一.标识符 (1)标识符就是在编写程序时给类,变量,方法等起的名字 (2)标识符的命名规则:标识符由字母,数字,下划线和$组成;第一个字符不能是数字;不能与关键字重名 二.关键字 定义:也称保留字,是 ...

  2. Nginx详解十三:Nginx场景实践篇之防盗链

    防盗链: 目的:防止资源被盗用 防盗链设置思路 首要方式:区别哪些请求是非正常的用户请求 基于http_refer防盗链配置模块(判断refer(上一步的链接)信息是否为允许访问的网站) 配置语法:v ...

  3. linux ssh远程免密码登入

    首先登入一台linux服务器,此台做为母机(即登入其他linux系统用这台做为入口):执行一行命令生成key文件:ssh-keygen -t rsa 2 在母机上,进入/roo/.ssh目录,找到id ...

  4. 论文阅读笔记二-ImageNet Classification with Deep Convolutional Neural Networks

    分类的数据大小:1.2million 张,包括1000个类别. 网络结构:60million个参数,650,000个神经元.网络由5层卷积层,其中由最大值池化层和三个1000输出的(与图片的类别数相同 ...

  5. VS和IIS的一些问题

    运行所有MVC一直502,重启了iis服务, 之后弹出这个框: 之后的解决办法: 1. If you open the applicationhost,config file in VS while ...

  6. SQLServer 常见高CPU利用率原因

    1.缺失索引: USE AdventureWorks2014 SET STATISTICS TIME ON; SET STATISTICS IO ON ; SELECT per.FirstName,p ...

  7. 谷歌浏览器Software Reporter Tool长时间占用CPU解决办法

    什么是Software Reporter Tool Software Reporter Tool是一个Chrome清理工具,用于清理谷歌浏览器中不必要或恶意的扩展,应用程序,劫持开始页面等等.当你安装 ...

  8. 一脸懵逼加从入门到绝望学习hadoop之Caused by: java.net.UnknownHostException: master报错

    windows下开发hadoop应用程序,hadoop部署在linux环境中, 在运行调试时可能会出现无法找到主机,类似异常信息如下: java.net.UnknownHostException: u ...

  9. [转] babel-plugin-react-css-modules配置

    自己的react项目用到了css-modules,由于不太想在写className时写style.xxx于是google解决方案,找到了这货->babel-plugin-react-css-mo ...

  10. mongodb实现自增的方法

    前面操作看菜鸟教程 function getNextSequenceValue(sequenceName){ var sequenceDocument = Counter.findOneAndUpda ...