卧薪尝胆,厚积薄发。
POETIZE6 IncDec Sequence
Date: Wed Sep 19 17:37:12 CST 2018
In Category:
NoCategory
Description:
给定一个长度为
$n$
的数列
$a_1,a_2,\cdots,a_n$
,每次可以选择一个区间
$[l,r]$
,使这个区间内的数都加
$1$
或者都减
$1$
。问至少需要多少次操作才能使数列中的所有数都一样,并求出在保证最少次数的前提下,最终得到的数列有多少种。
$1\le n \le 100000$
Solution:
不难想到差分后转化为使得
$2\sim n$
都为
$0$
,每一次操作可以任选两个一个加一一个减一,或者选一个加一或减一,为了让操作数最少应该尽量选操作两个的,于是统计一下差分数组正权之和
$ans1$
和负权之和
$ans2$
,第一问的答案就是
$\min(ans1,ans2)+|ans1-ans2|=\max(ans1,ans2)$
,第二问的话,首先
$min(ans1,ans2)$
的操作是不会变的,
$|ans1-ans2|$
这些操作可以操作在
$1$
上也可以操作在
$n+1$
上,每一种都对应一个最终结果,所以第二问的答案就是
$|ans1-ans2|+1$
。
Code:
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
typedef long long ll;
inline ll read()
{
register ll res = 0;
register char c = getchar();
while(!isdigit(c))c = getchar();
while(isdigit(c))
{
res = (res << 1) + (res << 3) + c - '0';
c = getchar();
}
return res;
}
int n;
#define MAXN 100010
ll a[MAXN];
int main()
{
scanf("%d",&n);
for(int i = 1;i <= n;++i)a[i] = read();
ll ans1 = 0,ans2 = 0;
for(int i = 2;i <= n;++i)
{
if(a[i] >= a[i - 1])ans1 += a[i] - a[i - 1];
else ans2 += a[i - 1] - a[i];
}
cout << max(ans1,ans2) << endl << llabs(ans1 - ans2) + 1 << endl;
return 0;
}
In tag:
技巧-差分
Copyright © 2020
wjh15101051
ღゝ◡╹)ノ♡