luogu P4243 [JSOI2009]等差数列 题解
前言:
这题真ex。。。

强烈谴责在题解里面放毒瘤题链接的屑出题人!
吐 ️
解析:
这题分成两步走。
首先,既然题目中的修改操作是区间加等差数列,那么就容易想到在差分数组上进行操作。
然后就是相当恶心的查询。
转化到差分数组上,相信会有一部分小朋友会向我一样,傻乎乎的以为就是求一个区间极大相同连续段个数。。。
其实我是联想到了这个题。。虽说线段树维护的思路是相似的,但是显然这道黑题比那个树剖难维护的多。。。
回到这个题。刚才说到,求区间极大相同连续段个数其实是不行的。
因为可以发现下面的数组:
3,4,6,9
差分以后是这个值:
3,1,2,3
算极大相同连续段个数的话,就可以发现,得出的答案是4。
但其实答案是2。
错误原因是,假如差分数组中的某个极大相同连续段长度是1的话,它对应的是原序列的两个数,比如是a[i],a[i+1]。假如下一个大相同连续段的长度还是1,那它对应的就是原序列的a[i+1]和a[i+2]。
于是a[i+1]就被算了两遍。
那怎么处理呢?
直接说线段树的维护方法了。
struct node{
int val,lval,rval,lc,rc,lrval;
};
struct Segment_tree{
node x;
int lazy;
}tree[maxn<<2];
上面的node结构体维护的是某个区间[l,r]的信息。
val表示区间[l,r]最少能划分成几段,lval表示区间(l,r]最少能划分成几段(即不算l),rval表示区间[l,r)最少能划分成几段(即不算r),lrval表示区间(l,r)最少能划分成几段(即不算l和r)。
lc表示[l,r]的最左端点的值,rc表示[l,r]的最右端点的值。
lazy即区间加和标记。
那就有柿子(以更新val为例):
tree[rt].x.val=tree[rt<<1].x.val+tree[rt<<1|1].x.val-(tree[rt<<1].x.rc==tree[rt<<1|1].x.lc);
//即尝试把左右的儿子区间连起来。
tree[rt].x.val=min(tree[rt].x.val,min(tree[rt<<1].x.rval+tree[rt<<1|1].x.val,tree[rt<<1].x.val+tree[rt<<1|1].x.lval));
//即把左右儿子区间断开,分中间点算到左边和中间点算到右边的两种情况
//三种情况取min即可。
然后,就可以维护了。。。。
当然,代码有亿点毒瘤...
亿点毒瘤的代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=100000+10;
int read(){
int w=0,x=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-') x=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
w=(w<<1)+(w<<3)+(ch^48);
ch=getchar();
}
return w*x;
}
int n,q;
int c[maxn];
struct node{
int val,lval,rval,lc,rc,lrval;
};
struct Segment_tree{
node x;
int lazy;
}tree[maxn<<2];
void pushup(int rt){
tree[rt].x.lc=tree[rt<<1].x.lc;
tree[rt].x.rc=tree[rt<<1|1].x.rc;
tree[rt].x.val=tree[rt<<1].x.val+tree[rt<<1|1].x.val-(tree[rt<<1].x.rc==tree[rt<<1|1].x.lc);
tree[rt].x.val=min(tree[rt].x.val,min(tree[rt<<1].x.rval+tree[rt<<1|1].x.val,tree[rt<<1].x.val+tree[rt<<1|1].x.lval));
tree[rt].x.lval=tree[rt<<1].x.lval+tree[rt<<1|1].x.val-(tree[rt<<1].x.rc==tree[rt<<1|1].x.lc);
tree[rt].x.lval=min(tree[rt].x.lval,min(tree[rt<<1].x.lrval+tree[rt<<1|1].x.val,tree[rt<<1].x.lval+tree[rt<<1|1].x.lval));
tree[rt].x.rval=tree[rt<<1].x.val+tree[rt<<1|1].x.rval-(tree[rt<<1].x.rc==tree[rt<<1|1].x.lc);
tree[rt].x.rval=min(tree[rt].x.rval,min(tree[rt<<1].x.rval+tree[rt<<1|1].x.rval,tree[rt<<1].x.val+tree[rt<<1|1].x.lrval));
tree[rt].x.lrval=tree[rt<<1].x.lval+tree[rt<<1|1].x.rval-(tree[rt<<1].x.rc==tree[rt<<1|1].x.lc);
tree[rt].x.lrval=min(tree[rt].x.lrval,min(tree[rt<<1].x.lrval+tree[rt<<1|1].x.rval,tree[rt<<1].x.lval+tree[rt<<1|1].x.lrval));
}
void build(int rt,int l,int r){
if(l==r){
tree[rt].x.val=tree[rt].x.lval=tree[rt].x.rval=1;//初始化要注意
tree[rt].x.lc=tree[rt].x.rc=c[l];
return;
}
int mid=(l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
pushup(rt);
}
void update(int rt,int x){
tree[rt].lazy+=x;
tree[rt].x.lc+=x;
tree[rt].x.rc+=x;
}
void pushdown(int rt){
if(tree[rt].lazy==0) return;
update(rt<<1,tree[rt].lazy);
update(rt<<1|1,tree[rt].lazy);
tree[rt].lazy=0;
}
void modify(int rt,int l,int r,int s,int t,int p){
if(s<=l&&r<=t){
update(rt,p);
return;
}
int mid=(l+r)>>1;
pushdown(rt);
if(s<=mid) modify(rt<<1,l,mid,s,t,p);
if(t>mid) modify(rt<<1|1,mid+1,r,s,t,p);
pushup(rt);
}
node query(int rt,int l,int r,int s,int t){
if(s<=l&&r<=t) return tree[rt].x;
int mid=(l+r)>>1;
pushdown(rt);
if(t<=mid) return query(rt<<1,l,mid,s,t);
if(s>mid) return query(rt<<1|1,mid+1,r,s,t);
node resl=query(rt<<1,l,mid,s,t);
node resr=query(rt<<1|1,mid+1,r,s,t);
node res={};
res.lc=resl.lc;
res.rc=resr.rc;
res.val=resl.val+resr.val-(resl.rc==resr.lc);
res.val=min(res.val,min(resl.rval+resr.val,resl.val+resr.lval));
res.lval=resl.lval+resr.val-(resl.rc==resr.lc);
res.lval=min(res.lval,min(resl.lval+resr.lval,resl.lrval+resr.val));
res.rval=resl.val+resr.rval-(resl.rc==resr.lc);
res.rval=min(res.rval,min(resl.rval+resr.rval,resl.val+resr.lrval));
res.lrval=resl.lval+resr.rval-(resl.rc==resr.lc);
res.lrval=min(res.lrval,min(resl.lrval+resr.rval,resl.lval+resr.lrval));
return res;
}
void Solve(){
n=read();
int la=0;
for(int i=1,x;i<=n;++i){
x=read();
c[i]=x-la;
la=x;
}
build(1,1,n);
q=read();
char ccc[3];
for(int i=1,s,t,x,y;i<=q;++i){
scanf("%s",ccc);
s=read();
t=read();
if(ccc[0]=='B'){
if(s==t||s==t-1) printf("1\n");
else{
node ans=query(1,1,n,s+1,t);
printf("%lld\n",ans.val);
}
}else{
x=read();
y=read();
modify(1,1,n,s,s,x);
if(s<t) modify(1,1,n,s+1,t,y);
if(t<n) modify(1,1,n,t+1,t+1,-1*(x+y*(t-s)));
}
}
}
signed main(){
Solve();
return 0;
}
luogu P4243 [JSOI2009]等差数列 题解的更多相关文章
- 洛谷P4243/bzoj1558 [JSOI2009]等差数列(线段树维护差分+爆炸恶心的合并)
题面 首先感谢这篇题解,是思路来源 看到等差数列,就会想到差分,又有区间加,很容易想到线段树维护差分.再注意点细节,\(A\)操作完美解决 然后就是爆炸恶心的\(B\)操作,之前看一堆题解的解释都不怎 ...
- 【题解】Luogu P4054 [JSOI2009]计数问题
原题传送门 我自闭了qaq 这道题非常简单,因为1<=c<=100,所以直接对每个c开二维树状数组,操作就跟模板一样 写码5分钟,调码半小时,这道题的输入顺序是x1,x2,y1,y2,我真 ...
- [bzoj1558][JSOI2009]等差数列
题目:给定n个数,m个操作,每次给一段区间加一个等差数列或者询问一段区间至少要用多少个等差数列来表示.$n,m\leqslant 10^{5}$ 题解:老套路,维护差分数组,修改操作变成了两个单点加和 ...
- BZOJ.1558.[JSOI2009]等差数列(线段树 差分)
BZOJ 洛谷 首先可以把原序列\(A_i\)转化成差分序列\(B_i\)去做. 这样对于区间加一个等差数列\((l,r,a_0,d)\),就可以转化为\(B_{l-1}\)+=\(a_0\),\(B ...
- [JSOI2009]等差数列
链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1558 题解: 考虑这么用线段树进行维护,由于他有区间修改等差数列 很容易想到可以用差分数组来维 ...
- BZOJ1558 [JSOI2009]等差数列 【线段树】
题目链接 BZOJ1558 题解 等差数列,当然是差分一下 差分值相同的连续位置形成等差数列,我们所选的两个等差数列之间可以有一个位置舍弃 例如: \(1 \; 2 \; 3 \; 6 \; 8 \; ...
- 【luogu P5022 旅行】 题解
题目连接:https://www.luogu.org/problemnew/show/P5022 \(NOIP2018 DAY2T1\) 考场上只写了60分,很容易想到当 m = n - 1 时的树的 ...
- JSOI2009 等差数列 和 算术天才⑨与等差数列 和 CH4302 Interval GCD
等差数列 为了检验学生的掌握情况,jyy布置了一道习题:给定一个长度为N(1≤N≤100,000)的数列,初始时第i个数为vi(vi是整数,−100,000≤vi≤100,000),学生们要按照jyy ...
- bzoj 1558: [JSOI2009]等差数列
Description Solution 把原数组变为差分数组,然后剩下的就十分显然了 区间查询用线段树维护 修改操作就是区间加法和两个单点修改 一个等差数列实际上就是 开头一个数字+数值相等的一段 ...
随机推荐
- (3)java Spring Cloud+Spring boot+mybatis企业快速开发架构之SpringCloud-Spring Cloud和Dubbo的区别及各自的优缺点
我们先从 Nginx 说起,了解为什么需要微服务.最初的服务化解决方案是给相同服务提供一个统一的域名,然后服务调用者向这个域发送 HTTP 请求,由 Nginx 负责请求的分发和跳转. 这种架构存 ...
- lombok时运行编译无法找到get/set方法 看这篇就够了
今天项目突然运行的时候报错,提示找不到get和set方法,这个时候我就检查了项目,在编译器(idea)是没有报错的.说明编译没问题,只是运行过不去. 后面就开始用我的方法解决这个问题,一步一步排查. ...
- POJ2352 Stars (静态二叉检索树)
https://vjudge.net/problem/POJ-2352 分析: 由于是按照y坐标的升序,y坐标向等的按x的升序的顺序给出星星.那么某个星星的等级数就是在他前面x坐标小于等于他的x坐标的 ...
- Django学习day05随堂笔记
每日测验 """ 今日考题 1.反向解析的本质是什么,无名和有名反向解析如何操作? 2..路由分发能够实现的前提是什么,需要注意什么,名称空间什么时候使用 3..什么是虚 ...
- 利用 uber-go/dig 库管理依赖
利用 uber-go/dig 库管理依赖 github 地址 官方文档 介绍 dig 库是一个为 go 提供依赖注入 (dependency injection) 的工具包,基于 reflection ...
- Hyper-V + WSL2与 VirtualBox 共存
Hyper-V + WSL2与 VirtualBox 共存 这样的教程网上有很多,我先简单复述一下.真正麻烦的是我遇到的问题--开启 Hyper-V 后我的电脑会多出几个删不掉的虚拟显示器来,会在文章 ...
- Charles的breakpoint功能
修改请求报文 比如,前端已经控制了输入内容,而我们需要验证接口是否做了校验,这时候怎么测试? 可以通过charles抓包,修改请求报文,修改为在页面上无法输入的内容,发出去然后看后台怎么处理. 修改返 ...
- react 的一些学习资料
* react开发实战 (Pro React) https://github.com/apress/pro-react * react 配置好的环境https://github.com/bricksp ...
- 使用Jmeter过程中遇到的问题
学习接口自动化测试框架或工具,UI自动化测试框架或工具,有时会觉得知识似乎比较零散,死记硬背不是一个好方法.一个学习的思路是思考使用这些框架或工具的时候,可能会遇到什么问题,遇到这些问题可以通过什么方 ...
- php-抽象工厂
目标:创建有依赖关系的实例;(套餐) <?php //抽象类 食物 interface IAllayFood { function Allay(); } interface IDrinkFood ...