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

 

posted @ 2020-04-26 23:08  DeepJay  阅读(182)  评论(0编辑  收藏  举报