【题解】arc189_b Minimize Sum
arc189_b Minimize Sum
题意
给定长度为 \(n\) 的递增序列 \(a\),每次可以选择一个下标 \(i(i+3\le n)\) 进行操作:
- 将 \(a_{i+1}\) 和 \(a_{i+2}\) 分别以 \(a_i\) 和 \(a_{i+3}\) 的中点为对称点作对称变换。
求通过不限次操作后得到的 \(\displaystyle \sum_{i=1}^n a_i\) 的最小值。
题解
知识点:差分,贪心。
需要观察力的一道题。
设 \(A,B,C,D\) 分别为序列中四个相邻的数,且值分别为 \(a,b,c,d(a<b<c<d)\)。
\(A\) 和 \(D\) 的中点为 \(\frac{a+d}{2}\)。
则 \(B\) 和 \(C\) 作对称变换后值变为 \(a+d-c\) 和 \(a+d-b\)。
现在 \(A,B,C,D\) 值分别为 \(a,a+d-c,a+d-b,d\)。
在这个时候,如果你想到去作差分,那么你会发现原来 \(A,B,C,D\) 差分序列为 \(a,b-a,c-b,d-c\),变换后差分序列为 \(a,d-c,c-b,b-a\),在差分序列上就相当于交换了 \(B,D\)。
果断将原序列也作差分得到 \(d_i=a_i-a_{i-1}\),那么变为最小化 \(\displaystyle \sum_{i=1}^n \sum_{j=1}^i d_j\),显然更小的 \(d_i\) 被换到前面会让这个式子的值变小。
但交换不是能随便交换,发现除了 \(d_1\) 不能动(能参与交换的数下标至少为 \(2\))以外,下标奇偶性相同的 \(d_i\) 之间可以随便交换,故考虑对奇偶分别贪心。
#include<bits/stdc++.h>
using namespace std;
#define rep(i,l,r) for(int i=(l);i<=(r);++i)
#define per(i,l,r) for(int i=(r);i>=(l);--i)
#define pr pair<int,int>
#define fi first
#define se second
#define pb push_back
#define all(x) (x).begin(),(x).end()
#define sz(x) (int)(x).size()
#define bg(x) (x).begin()
#define ed(x) (x).end()
#define N 202507
#define int long long
int n,a[N];
vector<int>v[2];
signed main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n;
rep(i,1,n){
cin>>a[i];
}
per(i,1,n){
a[i]-=a[i-1];
if(i>=2){
v[i%2].pb(a[i]);
}
}
sort(all(v[0]));
sort(all(v[1]));
rep(i,0,sz(v[0])-1){
a[(i+1)*2]=v[0][i];
}
rep(i,0,sz(v[1])-1){
a[(i+1)*2+1]=v[1][i];
}
int ans=0;
rep(i,1,n){
a[i]+=a[i-1];
ans+=a[i];
}
cout<<ans;
return 0;
}

浙公网安备 33010602011771号