[bzoj3043]IncDec Sequence_差分
IncDec Sequence
题目大意:给定一个长度为n的数列{a1,a2...an},每次可以选择一个区间[l,r],使这个区间内的数都加一或者都减一。问至少需要多少次操作才能使数列中的所有数都一样,并求出在保证最少次数的前提下,最终得到的数列有多少种。
数据范围:对于100%的数据,n=100000,0<=ai<2147483648
题解:
首先,对于这种操作是区间加啊区间减啊的题,不难想到差分。
现在假设,$b_i = a_i - a_{i - 1}$,$b$序列有$n$个值。
我们要保证对于$2\le i\le n$,$b_i == 0$且操作次数最小。
现在假设,$b_2$到$b_n$中,所有正数的和是$S1$,所有负数的绝对值的和是$S_2$。
因为我们不用管$b_1$,所以我们就相当于有两种操作:
一种是$S1--$且$S1--$。
一种是$S1--$或$S2--$。
那么最小的操作次数显然就是$max(S1, S2)$。
最终的序列个数呢?
现在,每一种最终的差分序列都对应原序列,那么原序列个数就等于$b_1$的取值个数。
发现只有一种.......
这是为什么呢???
看看样例就发现了端倪:
我们发现,两种操作的第二种,是可以使得$b_1$的值不变,但是仍然挑一个$S$令其$-1$。
这就相当于对区间$[i, n]$实施操作。
故此呢,我们还需要弄一个$b_{n +1}$表示$-a_n$。
这样的话,每次二操作都是从$b_1$和$b_{n + 1}$中选一个$-1$。
一共有$max(S1,S2)-min(S1,S2)$次二操作的机会。
只需要分成两边就好,所以最终的序列一共有$max(S1,S2)-min(S1,S2) + 1$种。
代码:
#include <bits/stdc++.h>
#define N 100010
using namespace std;
int a[N], b[N];
typedef long long ll;
char *p1, *p2, buf[100000];
#define nc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1 ++ )
int rd() {
int x = 0, f = 1;
char c = nc();
while (c < 48) {
if (c == '-')
f = -1;
c = nc();
}
while (c > 47) {
x = (((x << 2) + x) << 1) + (c ^ 48), c = nc();
}
return x * f;
}
int main() {
int n = rd();
for (int i = 1; i <= n; i ++ )
a[i] = rd();
for (int i = 1; i <= n; i ++ ) {
b[i] = a[i] - a[i - 1];
}
ll S1 = 0, S2 = 0;
for (int i = 2; i <= n; i ++ ) {
if(b[i] < 0) {
S2 -= b[i];
}
else {
S1 += b[i];
}
}
if(S1 < S2)
swap(S1, S2);
printf("%lld\n%lld\n", S1, S1 - S2 + 1);
return 0;
}
小结:有的时候发现当前算法有些问题,但是有不知道哪里有问题,可以挑几组小数据玩一玩,会有收获的(确信。
[bzoj3043]IncDec Sequence_差分的更多相关文章
- 【bzoj3043】IncDec Sequence 差分
题目描述 给定一个长度为n的数列{a1,a2...an},每次可以选择一个区间[l,r],使这个区间内的数都加一或者都减一.问至少需要多少次操作才能使数列中的所有数都一样,并求出在保证最少次数的前提下 ...
- IncDec序列:差分+贪心
IncDec序列 题目描述: 给定一个长度为 n 的数列 a1,a2,…,an,每次可以选择一个区间[l,r],使下标在这个区间内的数都加一或者都减一. 求至少需要多少次操作才能使数列中的所有数都一样 ...
- bzoj3043 IncDec Sequence
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3043 [题解] 比较神奇的一道题,开始没往差分的角度上想,所以没想出来. 考虑查分数组,有$ ...
- 差分:IncDec Sequence 差分数组
突然就提到了这个东西,为了不再出现和去年联赛看见二分没学二分痛拿二等第一的情况,就去学了一下,基础还是比较简单的-- 先看一个经典例题: 给定一个长度为n的数列{a1,a2...an},每次可以选择一 ...
- BZOJ 3043: IncDec Sequence 差分 + 思维
Code: #include <bits/stdc++.h> #define setIO(s) freopen(s".in","r",stdin) ...
- 差分【bzoj3043】IncDec Sequence
Description 给定一个长度为n的数列{a1,a2...an},每次可以选择一个区间[l,r],使这个区间内的数都加一或者都减一. 问至少需要多少次操作才能使数列中的所有数都一样,并求出在保证 ...
- 【BZOJ3043】IncDec Sequence 乱搞
[BZOJ3043]IncDec Sequence Description 给定一个长度为n的数列{a1,a2...an},每次可以选择一个区间[l,r],使这个区间内的数都加一或者都减一.问至少需要 ...
- 【BZOJ 3043】 3043: IncDec Sequence (差分)
3043: IncDec Sequence Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 589 Solved: 332 Description 给 ...
- IncDec Sequence(差分)
题意:给定一个序列,可以对一个区间进行加1或减1的操作,问最少需要多少次可以将序列的值一样. Solution 我们将序列差分,得到一个差分数组. 对于每一个区间操作,我们可以把它转化为在查分数组上某 ...
随机推荐
- BZOJ 2982 combination 脑子+组合数学
可以发现,整个数列构成一个树形结构,并且是个完全二叉堆(小根堆). 并且这个堆的形态在给定$n$后是固定的,第1个位置上显然只能放1. 对子树的根来说,他自己是所分得的数集中最小的那个,所以从剩下$s ...
- 如何复制word的图文到ueditor中自动上传?
官网地址http://ueditor.baidu.com Git 地址 https://github.com/fex-team/ueditor 参考博客地址 http://blog.ncmem.com ...
- Ubuntu 出现 Invalid operation update 或 Invalid operation upgrade的解决办法
输入 sudo apt update && sudo apt full-upgrade
- js面向对象学习笔记
1.函数的定义方式 第一种定义方式 function fn1() { alert("fn1"); } alert(fn) 函数就是一个特殊的对象,是一个Function类的实例,其 ...
- Pytest学习笔记(一) 环境安装及入门
简介 pytest是python的一个单元测试框架,类似于unittest,相对unittest来说,pytest使用更简单,功能更强大. 安装 pip3 install -U pytest 查看版本 ...
- 2个最好的JavaScript编辑器 必须要知道
JavaScript程序员有许多很好的工具可供选择,几乎太多了.在这篇文章中,介绍2个最好用的文本编辑器,也是顶级的.并且很好地支持使用JavaScript,HTML5和CSS进行开发,并用Markd ...
- JS基础_数组的遍历
遍历:将数组中所有的元素都取出来 1.for循环 var arr = ["1","2","3"]; for(let i=0;i<arr ...
- vue 动态渲染数据很慢或不渲染
vue 动态渲染数据很慢或不渲染 原因是因为vue检测速度很慢,因为多层循环了,在VUE 2.x的时候还能渲染出来,1.x的时候压根渲染不出来.解决方式:在动态改变数据的方法,第一行加上 this.$ ...
- OpenWrt下如何配置网络?
答: 使用uci进行配置,示例如下: uci get network.wan.ifname (笔者得到eth1) uci set network.wan.ifname=ethx (如: uci set ...
- 份-城市,基于jQuery的AJAX二级联动,用Struts2整合AJAX【非数据库版】
package loaderman.provincecity; import java.io.IOException; import java.util.LinkedHashSet; import j ...