前言
好难的一题
传送门 :
前言
对于差分操作,如果一个区间加上一个常数c: 如下
d
[
l
]
+
=
c
,
d
[
r
]
−
=
c
(
d
为
差
分
数
组
)
d[l]+=c\ \ \ , \ \ \ d[r]-=c \ \ \ (d为差分数组)
d[l]+=c , d[r]−=c (d为差分数组)
如果一个数组所有数都一样也就是说明差分数组为0
又因为 :
b
[
1
]
=
a
[
1
]
,
b
[
2
]
=
a
[
2
]
−
a
[
1
]
,
b
[
3
]
=
a
[
3
]
−
a
[
2
]
.
.
.
.
.
b[1] = a[1],b[2]=a[2]-a[1],b[3]=a[3]-a[2].....
b[1]=a[1],b[2]=a[2]−a[1],b[3]=a[3]−a[2].....
因此这个题目可以转换为, 从 [ 2 − n ] [2-n] [2−n]选出两个数,一个 + 1 +1 +1,一个 − 1 -1 −1,使得 b [ 2.. n ] = 0 b[2..n] = 0 b[2..n]=0
这样子数组就变为了 n n n个 a [ 1 ] a[1] a[1] , 这样子显然的我们尽可能需选出 b [ l ] ∗ b [ r ] < 0 b[l]*b[r]<0 b[l]∗b[r]<0
因为这样子才可以让每次操作都有意义,所以对于如下操作有一下几种操作
- 2 < = l , r < = n 2<=l,r<=n 2<=l,r<=n
- l = 1 , 2 < = r < = n l=1,2<=r<=n l=1,2<=r<=n
- 2 < = l < = n , r = n + 1 2<=l<=n,r =n+1 2<=l<=n,r=n+1
- l = 1 , r = n + 1 l = 1, r =n+1 l=1,r=n+1(没意义,显然的)
为什么会出现中间两种呢 ? 因为如果数组中的 s u m ( b [ i ] > 0 ) ! = s u m ( b [ i ] < 0 ) sum(b[i]>0) != sum(b[i]<0) sum(b[i]>0)!=sum(b[i]<0),
那么我们只能,对 1 ∣ ∣ n + 1 1||n+1 1∣∣n+1进行操作,使得我们的操作可以进行下去
因为最小的操作次数 = m i n ( s 1 , s 2 ) + a b s ( s 1 − s 2 ) min(s1,s2) + abs(s1-s2) min(s1,s2)+abs(s1−s2)
因为数组最后都是 a [ 1 ] a[1] a[1],所以也就是询问 a [ 1 ] a[1] a[1]的可能值
所以种类数= a b s ( s 2 − s 1 ) + 1 abs(s2-s1)+1 abs(s2−s1)+1
当然一开始我是没想到的,直接口胡了一个答案,虽然样例过了但是爆 L L LL LL了
CODE
const int N = 1e5+10;
int a[N],d[N];
int n;
void solve()
{
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
d[i] = a[i] - a[i-1];
}
ll p = 0 ,q = 0 ;
for(int i=2;i<=n;i++){
if(d[i]>0)
p+=d[i];
else
q-=d[i];
}
cout<<min(p,q)+abs(p-q)<<endl;
cout<<abs(p-q)+1<<endl;
}
signed main()
{
//int t;cin>>t;while(t -- )
solve();
return 0;
}