链接: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]等差数列的更多相关文章

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

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

  2. [bzoj1558][JSOI2009]等差数列

    题目:给定n个数,m个操作,每次给一段区间加一个等差数列或者询问一段区间至少要用多少个等差数列来表示.$n,m\leqslant 10^{5}$ 题解:老套路,维护差分数组,修改操作变成了两个单点加和 ...

  3. 洛谷P4243/bzoj1558 [JSOI2009]等差数列(线段树维护差分+爆炸恶心的合并)

    题面 首先感谢这篇题解,是思路来源 看到等差数列,就会想到差分,又有区间加,很容易想到线段树维护差分.再注意点细节,\(A\)操作完美解决 然后就是爆炸恶心的\(B\)操作,之前看一堆题解的解释都不怎 ...

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

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

  5. BZOJ1558 [JSOI2009]等差数列 【线段树】

    题目链接 BZOJ1558 题解 等差数列,当然是差分一下 差分值相同的连续位置形成等差数列,我们所选的两个等差数列之间可以有一个位置舍弃 例如: \(1 \; 2 \; 3 \; 6 \; 8 \; ...

  6. JSOI2009 等差数列 和 算术天才⑨与等差数列 和 CH4302 Interval GCD

    等差数列 为了检验学生的掌握情况,jyy布置了一道习题:给定一个长度为N(1≤N≤100,000)的数列,初始时第i个数为vi(vi是整数,−100,000≤vi≤100,000),学生们要按照jyy ...

  7. luogu P4243 [JSOI2009]等差数列 题解

    前言: 这题真ex... 强烈谴责在题解里面放毒瘤题链接的屑出题人! 吐 ️ 解析: 这题分成两步走. 首先,既然题目中的修改操作是区间加等差数列,那么就容易想到在差分数组上进行操作. 然后就是相当恶 ...

  8. Noip前的大抱佛脚----赛前任务

    赛前任务 tags:任务清单 前言 现在xzy太弱了,而且他最近越来越弱了,天天被爆踩,天天被爆踩 题单不会在作业部落发布,所以可(yi)能(ding)会不及时更新 省选前的练习莫名其妙地成为了Noi ...

  9. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

随机推荐

  1. JAVA中equals方法与hashCode方法学习

    首先参考文章:http://www.oschina.net/translate/working-with-hashcode-and-equals-methods-in-java 1,equals方法的 ...

  2. vue 裁剪图片,插件Cropper的使用

    全局安装    npm install cropperjs 如果想本项目安装,方便移植:   import Cropper from 'cropperjs'   --save    这样的话,本地 p ...

  3. ELF格式探析之三:sections

    前文链接: ELF格式探析之一:Segment和Section ELF格式探析之二:文件头ELF Header详解 今天我们讲对目标文件(可重定位文件)和可执行文件都很重要的section. 我们在讲 ...

  4. u-boot移植(九)---代码修改---NAND

    一.NAND原理 NAND 无地址空间,地址和数据的发送都依赖于LDATA[0:7]这一串数据总线. 不看随机页编程,看到从高位到低位的页,总共分为64个页面,每个页的组成是2K + 64  个byt ...

  5. scapy官方文档

    https://thepacketgeek.com/scapy-p-04-looking-at-packets/ http://biot.com/capstats/bpf.html   filter语 ...

  6. 20155231 2016-2017-2 《Java程序设计》第6周学习总结

    20155231 2016-2017-2 <Java程序设计>第6周学习总结 教材学习内容总结 学习目标 理解流与IO 理解InputStream/OutPutStream的继承架构 理解 ...

  7. android ListView使用

    1.DbOpenHelper package dbOpenHelper; import android.content.Context; import android.database.sqlite. ...

  8. 【centos】 error: command 'gcc' failed with exit status 1

    原文连接http://blog.csdn.net/fenglifeng1987/article/details/38057193 用安装Python模块出现error: command 'gcc' f ...

  9. 解决kali linux 开启ssh服务后连接不上的问题

    今天在手机端装了NetHunter 想连接PC的kali ,可是怎么都连不上 综合网友的经验: 1.修改sshd_config文件,命令为:vi /etc/ssh/sshd_config 将#Pass ...

  10. QT中QString 与 int float double 等类型的相互转换

    Qt中 int ,float ,double转换为QString 有两种方法 1.使用 QString::number(); 如: long a = 63; QString s = QString:: ...