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; }