[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 ...
随机推荐
- C#析构函数与Dispose
有几种不同的操作方式 方式一: namespace ConsoleApp1 { class Test { ~Test()// 析构函数 { ...
- 逆向安全基础之IDA使用简介
转载:http://m.blog.csdn.net/ilnature2008/article/details/54912854 IDA简介 IDA是业界一个功能十分强大的反汇编工具,是安全渗透人员进行 ...
- Protues常用元器件查找对应表
原理图常用库文件:Miscellaneous Devices.ddbDallas Microprocessor.ddbIntel Databooks.ddbProtel DOS Schematic L ...
- 【转】Python之装饰器
[转]Python之装饰器 本节内容 必要知识回顾 情景模拟 装饰器的概念及实现原理 回马枪(带参数的装饰器) 一. 必要知识回顾 在开始说装饰器之前,需要大家熟悉之前说过的相关知识点: 函数即“变量 ...
- [转]SPI通信原理简介
[转自]http://www.cnblogs.com/deng-tao/p/6004280.html 1.前言 SPI是串行外设接口(Serial Peripheral Interface)的缩写.是 ...
- DMA内存申请--dma_alloc_coherent 及 寄存器与内存【转】
转自:https://blog.csdn.net/ic_soc_arm_robin/article/details/8203933 在项目驱动过程中会经常用到dma传输数据,而dma需要的内存有自己的 ...
- SharePoint 2010:“&”作为SharePoint账号密码引起的错误
一朋友修改了SharePoint 2010系统账号密码,导致无法登陆.他的环境如下: 两台服务器:AD+SharePoint 2010 ,Sql Server 2008 r2 目标站点开启了Form登 ...
- Windows CreateFont:创建自己的字体
原文地址:http://blog.csdn.net/softn/article/details/51718347 前面无论是使用文本输出函数还是 static 控件,字体都是默认的,比较丑陋,我们完全 ...
- navicat报caching_sha2_password异常
使用navicat连接mysql报错(升级到mysql8版本时的错) 解决办法: 通过命令行登录mysql后, 输入: alter user 'root'@'localhost' IDENTIFIED ...
- centos6.5环境利用scp实现自动化文件备份
centos6.5环境利用scp自动上传备份文件到指定服务器中 需要备份的主机 192.168.3.17 存放备份的主机 192.168.3.18 目的:将3.17主机上/data/storage的文 ...