Codeforces1343D Constant Palindrome Sum(差分)

Posted shuitiangong

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces1343D Constant Palindrome Sum(差分)相关的知识,希望对你有一定的参考价值。

题目链接OvO

题目大意

??给一个长度为偶数且每个元素不大于(k)的正整数序列,你可以让任意一个元素修改为一个不大于(k)的正整数,求使每对(a_i)(a_{n-i+1}(ileq frac{n}{2}))的和都相等的最小修改次数。

分析

??对于每对数来说,它们可修改得到数字都有一个上界和一个下界,上界就是让最小的数变成(k),下界就是让最大的数变成(1)。假设答案中的序列任意两对数之和都为(x),那么对于问题中的每每对数,如果小于或者大于它们的上下界的话,那么就得修改两次;如果在上下界之内的话就得修改一次;特别的,如果等于两数之和,则不用修改。

解题思路

??性质很好分析但是怎么利用它呢?之前想过二分,但是没成到现在也不知道怎么改,看到大家都是用差分数组做的,这样做出来时间复杂度也比二分更低。大致思路就是用差分数组计算每个数对于各个范围之内的数的贡献。

如果位于上下界之外

??令下界(sub[2] += 2, sub[minn] -= 2)和上界(sub[maxx+1] += 2, sub[2*k+1]-=2)(也就是对于某对数(x)([2,minn-1]cup [maxx+1,2 imes k])之内的值都要修改两次)

如果位于上下界之内

??令(sub[minn] += 1,sub[maxx+1] -= 1)对应(x)取在上下界之内的情况

如果位于上下界之内刚好等于(x)

??令(sub[arr[i]+arr[n-i+1]] -= 1, sub[arr[i]+arr[n-i+1]+1] += 1)也就是说当(x)取这个值的时候贡献为(0)

代码

const int maxn = 2e5+10;
int arr[maxn], sub[maxn<<1];
int main(void) {
    int t;
    scanf("%d", &t);
    while(t--) {
        int n, k;
        scanf("%d%d", &n, &k);
        memset(sub, 0, sizeof(sub[0])*(2*k+5));
        for (int i = 1; i<=n; ++i) scanf("%d", &arr[i]);
        for (int i = 1; i<=n/2; ++i) {
            int maxx = max(arr[i], arr[n-i+1])+k;
            int minn = min(arr[i], arr[n-i+1])+1;
            sub[2] += 2; sub[minn] -= 2;
            sub[maxx+1] += 2; //sub[2*k+1]-=2就不写了,用不上
            sub[minn] += 1; sub[maxx+1] -= 1;
            sub[arr[i]+arr[n-i+1]] -= 1; sub[arr[i]+arr[n-i+1]+1] += 1;
        }
        int ans = INF;
        for (int i = 2; i<=2*k; ++i) {
            sub[i] += sub[i-1];
            ans = min(ans, sub[i]);
        }
        printf("%d
", ans);
    }
    return 0;
}

以上是关于Codeforces1343D Constant Palindrome Sum(差分)的主要内容,如果未能解决你的问题,请参考以下文章

CF 1343 D. Constant Palindrome Sum

Approximating a Constant Range

#333 Div2 Problem B Approximating a Constant Range(尺取法)

tf.constant

Constant Pool和String Constant Pool详解

常量指针(pointer to constant)和指针常量(constant pointer)