[JSOI2009]等差数列
链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1558
题解:
考虑这么用线段树进行维护,由于他有区间修改等差数列
很容易想到可以用差分数组来维护(这东西经常和数据结构用在一起)
那么每一次的区间修改就变成了单点修改
另外我们可以利用线段树来维护:
h---t区间等差数列个数,h----(t-1)区间等差数列个数,(h+1)---t区间等差数列个数
为了维护这三个值,要引入(h+1)-----(t-1)(这个转移非常巧妙)
为什么要维护这些呢,因为我们算一个就可以发现
当他们不是一个等差数列时,区间中有一个数是没有用的
由于进行了差分,等差数列其实就是差分数组的值相同
bzoj re了 并不知道为什么 对拍是对的
代码:
#include <bits/stdc++.h>
#define maxn 311111
#define mid (p[x].h+p[x].t)/2
using namespace std;
int n,m,a[maxn*],b[maxn*];
struct re
{
int h,t,sum,sum1,sum2,sum3,lazy,hnum,tnum;
}p[maxn*];
struct ree
{
int sum,sum1,sum2;
};
void updata(int x)
{
p[x].sum=min(p[x*].sum2+p[x*+].sum,p[x*].sum+p[x*+].sum1);
p[x].sum1=min(p[x*].sum3+p[x*+].sum,p[x*].sum1+p[x*+].sum1);
p[x].sum2=min(p[x*].sum2+p[x*+].sum2,p[x*].sum+p[x*+].sum3);
p[x].sum3=min(p[x*].sum3+p[x*+].sum2,p[x*].sum1+p[x*+].sum3);
if (p[x*].tnum==p[x*+].hnum)
{
p[x].sum=min(p[x].sum,p[x*].sum+p[x*+].sum-);
p[x].sum1=min(p[x].sum1,p[x*].sum1+p[x*+].sum-);
p[x].sum2=min(p[x].sum2,p[x*].sum+p[x*+].sum2-);
p[x].sum3=min(p[x].sum3,p[x*].sum1+p[x*+].sum2-);
}
}
void build(int x,int h,int t)
{
p[x].h=h; p[x].t=t;
p[x].hnum=b[p[x].h];
p[x].tnum=b[p[x].t];
if (p[x].h==p[x].t)
{
p[x].sum=p[x].sum1=p[x].sum2=;p[x].sum3=; return;
}
build(x*,h,mid); build(x*+,mid+,t);
updata(x);
}
void down(int x)
{
if (p[x].lazy)
{
p[x].hnum+=p[x].lazy;
p[x].tnum+=p[x].lazy;
if (p[x].h!=p[x].t)
{
p[x*].lazy+=p[x].lazy;
p[x*+].lazy+=p[x].lazy;
}
p[x].lazy=;
}
}
void change(int x,int h,int t,int sum)
{
down(x);
if (p[x].h>t||p[x].t<h) return;
if (h<=p[x].h&&p[x].t<=t)
{
p[x].lazy+=sum; down(x);
return;
}
if (p[x].h<=t&&p[x].h>=h) p[x].hnum+=sum;
if (p[x].t<=t&&p[x].t>=h) p[x].tnum+=sum;
change(x*,h,t,sum);
change(x*+,h,t,sum);
updata(x);
}
re query(int x,int h,int t)
{
down(x);
re now;
if (h<=p[x].h&&p[x].t<=t)
{
now=p[x];
return(now);
}
if (mid+>t) return(query(x*,h,t));
if (mid<h) return(query(x*+,h,t));
re a=query(x*,h,t),b=query(x*+,h,t);
now.sum=min(a.sum2+b.sum,a.sum+b.sum1);
now.sum1=min(a.sum3+b.sum,a.sum1+b.sum1);
now.sum2=min(a.sum2+b.sum2,a.sum+b.sum3);
now.sum3=min(a.sum3+b.sum2,a.sum1+b.sum3);
if (p[x*].tnum==p[x*+].hnum)
{
now.sum=min(now.sum,a.sum+b.sum-);
now.sum1=min(now.sum1,a.sum1+b.sum-);
now.sum2=min(now.sum2,a.sum+b.sum2-);
now.sum3=min(now.sum3,a.sum1+b.sum2-);
}
return(now);
}
int main()
{
freopen("noip.in","r",stdin);
freopen("noip.out","w",stdout);
std::ios::sync_with_stdio(false);
cin>>n;
for (int i=;i<=n;i++)
{
cin>>a[i];
b[i-a]=a[i]-a[i-];
}
build(,,n-);
//for (int i=1;i<=2*n;i++){cout<<p[i].h<<" "<<p[i].t<<" "<<p[i].sum<<endl;}
cin>>m;
char c;
for (int i=;i<=m;i++)
{
int a1,b1,c1,d1;
cin>>c;
if (c=='A')
{
cin>>a1>>b1>>c1>>d1;
change(,a1,b1-,d1);
if (a1!=) change(,a1-,a1-,c1);
change(,b1,b1,-(c1+(b1-a1)*d1));
}
if (c=='B')
{
cin>>a1>>b1; re x;
if (a1!=b1) x=query(,a1,b1-);
else x.sum=;
cout<<x.sum<<endl;
}
}
}
[JSOI2009]等差数列的更多相关文章
- bzoj 1558: [JSOI2009]等差数列
Description Solution 把原数组变为差分数组,然后剩下的就十分显然了 区间查询用线段树维护 修改操作就是区间加法和两个单点修改 一个等差数列实际上就是 开头一个数字+数值相等的一段 ...
- [bzoj1558][JSOI2009]等差数列
题目:给定n个数,m个操作,每次给一段区间加一个等差数列或者询问一段区间至少要用多少个等差数列来表示.$n,m\leqslant 10^{5}$ 题解:老套路,维护差分数组,修改操作变成了两个单点加和 ...
- 洛谷P4243/bzoj1558 [JSOI2009]等差数列(线段树维护差分+爆炸恶心的合并)
题面 首先感谢这篇题解,是思路来源 看到等差数列,就会想到差分,又有区间加,很容易想到线段树维护差分.再注意点细节,\(A\)操作完美解决 然后就是爆炸恶心的\(B\)操作,之前看一堆题解的解释都不怎 ...
- BZOJ.1558.[JSOI2009]等差数列(线段树 差分)
BZOJ 洛谷 首先可以把原序列\(A_i\)转化成差分序列\(B_i\)去做. 这样对于区间加一个等差数列\((l,r,a_0,d)\),就可以转化为\(B_{l-1}\)+=\(a_0\),\(B ...
- BZOJ1558 [JSOI2009]等差数列 【线段树】
题目链接 BZOJ1558 题解 等差数列,当然是差分一下 差分值相同的连续位置形成等差数列,我们所选的两个等差数列之间可以有一个位置舍弃 例如: \(1 \; 2 \; 3 \; 6 \; 8 \; ...
- JSOI2009 等差数列 和 算术天才⑨与等差数列 和 CH4302 Interval GCD
等差数列 为了检验学生的掌握情况,jyy布置了一道习题:给定一个长度为N(1≤N≤100,000)的数列,初始时第i个数为vi(vi是整数,−100,000≤vi≤100,000),学生们要按照jyy ...
- luogu P4243 [JSOI2009]等差数列 题解
前言: 这题真ex... 强烈谴责在题解里面放毒瘤题链接的屑出题人! 吐 ️ 解析: 这题分成两步走. 首先,既然题目中的修改操作是区间加等差数列,那么就容易想到在差分数组上进行操作. 然后就是相当恶 ...
- Noip前的大抱佛脚----赛前任务
赛前任务 tags:任务清单 前言 现在xzy太弱了,而且他最近越来越弱了,天天被爆踩,天天被爆踩 题单不会在作业部落发布,所以可(yi)能(ding)会不及时更新 省选前的练习莫名其妙地成为了Noi ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
随机推荐
- logback异步输出日志(生产者消费者模型),并非批量写入日志。
一直对logback异步输出日志误解为异步批量写入日志. 今天看了源代码. 首先logback的异步日志是如何配置的: <!-- 管理端用户行为日志异步输出,异步的log片段必须在同步段后面,否 ...
- 17. Spring Boot 配置嵌入式Servlet容器
一.如何定制和修改Servlet容器的相关配置 1.配置文件(ServerProperties): 优先级最高 server.port=8081 server.context‐path=/crud s ...
- Linux之常用命令【service】
补充说明 service命令 是Redhat Linux兼容的发行版中用来控制系统服务的实用工具,它以启动.停止.重新启动和关闭系统服务,还可以显示所有系统服务的当前状态. 语法 service(选项 ...
- [HNOI2009]最小圈 (二分答案+负环)
题面:[HNOI2009]最小圈 题目描述: 考虑带权的有向图\(G=(V,E)\)以及\(w:E\rightarrow R\),每条边\(e=(i,j)(i\neq j,i\in V,j\in V) ...
- [HEOI2015]定价 (贪心)
分类讨论大法好! \(solution:\) 先说一下我对这个题目的态度: 首先这一题是贪心,这个十分明显,看了一眼其他题解都是十分优秀的贪心,可是大家都没有想过吗:你们贪心都是在区间\([l,r]\ ...
- golang使用simplejson库解析复杂json
cnblogs原创 golang自带的json解析库encoding/json提供了json字符串到json对象的相互转换,在json字符串比较简单的情况下还是挺好用的,但是当json字符串比较复杂或 ...
- 20165227《网络对抗技术》Exp0 Kali安装 Week1
2018-2019-2 <网络对抗技术>Exp0 Kali安装 Week1 kali下载:镜像文件通过同学获得 kali具体安装步骤: 打开VMware,点击新建虚拟机,进行创建 创建完成 ...
- 2018-2019-2 网络对抗技术 20165230 Exp4 恶意代码分析
目录 1.实验内容 2.实验过程 任务一:系统运行监控 每隔五分钟记录自己的电脑,并进行分析 安装配置sysinternals里的sysmon工具 任务二:恶意软件分析 静态分析工具 ViruScan ...
- libSVM在matlab下的使用安装
1) 从LIBSVM的官网http://www.csie.ntu.edu.tw/~cjlin/libsvm/上下载最新版本的LIBSVM,当前版本为libsvm-3.18.zip 2) 解压压缩包到电 ...
- Java中在特定区间产生随机数
生成指定范围内的随机数 这个是最常用的技术之一.程序员希望通过随机数的方式来处理众多的业务逻辑,测试过程中也希望通过随机数的方式生成包含大量数字的测试用例.问题往往类似于: 如何随机生成 1~100 ...