1343D. Constant Palindrome Sum (差分)
题目:传送门
思路:突破点在于:明确枚举x时,x -> x+1 之间的关系 (区间数量增减);
设:Li = min(a[i] , a[n-i+1] ) +1 , Ri = max(a[i] , a[n-i+1] ) + k; 区间[ Li , Ri ] 表示 修改 a[i] or a[n-i+1] ,其和 能够达到的范围。
如果在a[i] 和 a[n-i+1] 之间修改一个数使之和能够为x ,那么 x 应该 在 [Li , Ri ] ; 如果 不需要修改就能达到 x ,那么x应该在 [ x , x ] 等价于 [ x , x+1 ) ;
根据上述推理,可以通过差分数组解决。 具体操作见代码
#include<bits/stdc++.h> #pragma GCC optimize(2) using namespace std; typedef long long LL; typedef pair<int,int> pii; typedef pair<double,double> pdd; const int N=2e5+5; const int inf=0x3f3f3f3f; const LL mod=998244353; const double eps=1e-9; const long double pi=acos(-1.0L); #define ls (i<<1) #define rs (i<<1|1) #define fi first #define se second #define pb push_back #define mk make_pair #define mem(a,b) memset(a,b,sizeof(a)) LL read() { LL x=0,t=1; char ch; while(!isdigit(ch=getchar())) if(ch=='-') t=-1; while(isdigit(ch)){ x=10*x+ch-'0'; ch=getchar(); } return x*t; } int a[N],d[N<<1]; int main() { int T=read(); while(T--) { int n=read(),k=read(); for(int i=1;i<=n;i++) a[i]=read(); for(int i=1;i<=n/2;i++) { int l=min(a[i],a[n-i+1])+1; int r=max(a[i],a[n-i+1])+k; int x=a[i]+a[n-i+1]; d[l]--; d[x]--; d[x+1]++; d[r+1]++; } int sum=n,ans=n; for(int i=1;i<=k*2;i++) { sum+=d[i]; //printf("%d%c",d[i],i==k?'\n':' '); ans=min(ans,sum); d[i]=0; } d[k*2+1]=0; printf("%d\n",ans); } return 0; }