1. 程式人生 > 其它 >2021國慶CSP/NOIP衝刺營 Contest06 B. 樹苗

2021國慶CSP/NOIP衝刺營 Contest06 B. 樹苗

【題意】

給定一個長度為偶數的1-n的排列

求最大化$\sum_{i=1}^{n-1}|p_{i+1}-p_i|$,在滿足上式最大時的最小操作次數

【分析】

顯然我們會貪心的考慮讓數列放成

小大小大小大 / 大小大小大小 這樣的形式

這樣除去最左最右兩個位置,每個位置的貢獻都是2次,大正小負

那麼我們就應該把第$\frac{n}{2}$個和第$\frac{n}{2}+1$個分別放在左右

然後考慮不在自己位置上的有多少個也就是需要多少次調換

【程式碼】

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5; int n,a[maxn],b[maxn]; int main() { int T,P; scanf("%d%d",&T,&P); while(T--) { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); int mid=n/2; ll sum=0; for(int i=mid+2;i<=n;i++) sum+=2ll*i;
for(int i=1;i<mid;i++) sum-=2ll*i; sum++; if(P==0) printf("%lld\n",sum); else { int res=0,res1=0; for(int i=1;i<=n;i++) b[i]=a[i]; if(b[1]!=mid) { res++; for(int i=2;i<=n;i++)
if(b[i]==mid) swap(b[1],b[i]); } if(b[n]!=mid+1) { res++; for(int i=1;i<n;i++) if(b[i]==mid+1) swap(b[i],b[n]); } for(int i=2;i<=n;i+=2) if(b[i]<mid) res++; res1=res; res=0; for(int i=1;i<=n;i++) b[i]=a[i]; if(b[1]!=mid+1) { res++; for(int i=2;i<=n;i++) if(b[i]==mid+1) swap(b[1],b[i]); } if(b[n]!=mid) { res++; for(int i=1;i<n;i++) if(b[i]==mid) swap(b[i],b[n]); } for(int i=2;i<=n;i+=2) if(b[i]>mid) res++; printf("%d\n",min(res1,res)); } } return 0; }