2021國慶CSP/NOIP衝刺營 Contest06 B. 樹苗
阿新 • • 發佈:2021-11-08
【題意】
給定一個長度為偶數的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; }