IncDec序列
Posted zhangjianjunab
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了IncDec序列相关的知识,希望对你有一定的参考价值。
题目
题解
首先,我们确定几个性质:
- 答案要正确,必须要保证操作次数最小(这不是废话吗(╯‵□′)╯︵┻━┻)。
- 对于同一个区间而言,只能存在(+)或(-)的操作,否则是浪费。
- 对于一个(+)操作而言,不能有和它相接的(+)操作,(-)操作也是,否则可以合并并造成更小的次数,如:(1-3)和(3-5)合并成(1-5)
- 如果存在(k)个加/减号操作:(+[i_1,j_1],+[i_2,j_2],...,+[i_k,j_k])且满足(i_1=1,j_k=n,i_t<=j_{t+1}),那么这个可以变成:(+[1,n],+[j_1,i_2]...,+[j_{k-1},i_{k}]),然后(+[1,n])去掉,次数减一,因此不存在这种情况,当然,通过这个可以推广出如果有(k)个加号操作:(+[i_1,j_1],+[i_2,j_2],...,+[i_k,j_k])且满足(i_t<=j_{t+1})那么就可以变成:(+[i_1,j_k],+[j_1,i_2]...,+[j_{k-1},i_{k}]),如果这时恰好有一个(-[i_1,j_k])就可以刚好抵消了,次数(-1),因此这个如果不成立。
- 不可能有(+[1,n])这种(SB)的操作。
- 在遵循上述操作的情况下,对于(+[i,j])操作而言,我们可以分成两个操作:(-[1,i-1])和(-[j+1,n]),我们称之为反操作,为什么对?因为这个区间(+1)不就意味着其它区间(-1)吗?当然,如果(i≠1,j≠n),那么就会产生多一次操作次数(因为(i=1)或(j=n)话,左边或者右边是没有数字的,所以只是对除了([i,j])以外的另外一个区间作反操作罢了,次数不会增加),当然你如果头贴硬生生去消除其中一个操作倒是可以,但是前提是得有一个([?,n])或者([1,?])的操作才可以消掉。
也许你不是很理解,我们举个栗子:
对于操作(+[2,3]),(n=6),那么反操作就是(-[1,1],-[4,6]),就会增加两个操作,而且如果存在(+[4,?])和(-[4,6])相互抵消的话,那么(+[2,3])和(+[4,?])是可以合并的,那你又会问那如果是(+[3,6])和它抵消呢?没错,这样就可以消掉了,但是就会产生一个(+[3,4])的操作,所以消掉了其中一个反操作的影响,但是别想利用这个消掉原本的操作来减少次数。但是不是有(+[4,6])就可以消掉了吗,但是([4,6])和[2,3]可以合并。因此可以说明存在一个([?,6])才可以消除影响(当然,对于(?>4)的时候,就是(-[4,6])把(+[?,6])吞并变成(+[4,?]))。
但是同时又不可能同时把两个同时消掉影响,不然以性质4,我们在原来的区间操作就可以让次数(-1)了(这也是为什么(i=1)或(j=n)的反操作无法消掉的原因)。
当然通过这个,我们就可以得到,每一个([1,?])或者([?,n])就可以让数字(+1)或者(-1)(自己取反操作肯定可以),当然,这个是对应的,消耗掉一个([1,?])就可以产生一个反符号的([?,n])。 - 操作序列顺序不影响结果。
- 如果两种操作序列的结果一样(不要求次数相同),这两种一定可以通过非反操作的操作互相转化。(这个我是真的不会证,只能说是它本来就是(+-)具有的性质吧。)
- 以(j)为结尾操作都是同号的,异号可以合并。
- [1,?]和[?,n]数量的差是固定的,对于固定的([?,n])而言,在满足性质1的情况下,操作序列的结果不会有任何改变,不管操作序列怎么变(因为中间的操作要取反操作必须有[1,?]和[?,n]的转化),而且([1,?])和([?,n])的操作符号绝对是反的,正的可以合并成一个操作,如:(+[1,3],+[5,n])可以合并成(-[4,4])一样,就不是最少操作次数了。
这些性质我们先不管它,先看第一问,最少操作次数?我们要搞清楚一件事情,区间加减其实就是差分数组的单点修改,那我们只需要把数组差分一下,然后对于成对(1)和(-1)匹配一下,那么对于单独的(1)或者是(-1),我们应该如何处理呢?仔细观察,我们发现([i,n])的操作,只会产生一个(1)或者一个(-1),与之成对的(-1/1)是在(n+1)的位置的,我们就不管它了,所以对于剩下的(1)或者(-1),我们就认为它是做了([i,n])的加减。
这样为什么是最优秀最少的呢?因为一次加或者减最多只能消除掉一对(1,-1),剩下的(1/-1)不就是需要一个一个操作慢慢消了吗?所以这种方式构造出来的就是最优解,而且这样子的构造还方便了我们一个事情,就是我们得到了有多少个([?,n]),根据性质(9),以(n)结尾的操作都是同号的,而且这样构造不会出现([1,?])的情况(因为差分是以第一个数字为标准),现在以(+[?,n])为例,如果以(n)结尾的操作都是(+)操作,那么我们可以去掉一个(+)号操作然后产生一个(-[1,?])同时让结果(-1),所以有多少个加号,就多了多少种结果(负号同理),所以答案就是(abs(差分[n])+1)就是在最小操作次数下面有多少种答案啦。
总是是讲完了,虽然我感觉讲得很乱,但至少把思路讲了。
大概就是证明了一个([?,n])的操作就可以让结果变(1)且操作次数不变的性质是对的。
代码
时间复杂度:(O(n))
#include<cstdio>
#include<cstring>
#define N 110000
using namespace std;
typedef long long LL;
LL a[N],b[N],n;
inline LL mymax(LL x,LL y){return x>y?x:y;}
inline LL zabs(LL x){return x<0?-x:x;}
int main()
{
scanf("%lld",&n);
for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
for(int i=1;i<n;i++)b[i]=a[i+1]-a[i];
LL q=0,p=0;
for(int i=1;i<n;i++)
{
if(b[i]>0)q+=b[i];
else p+=-b[i];
}
printf("%lld
",mymax(q,p));
printf("%lld
",zabs(q-p)+1);
return 0;
}
以上是关于IncDec序列的主要内容,如果未能解决你的问题,请参考以下文章