Codeforces1343D Constant Palindrome Sum(差分)
Posted shuitiangong
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces1343D Constant Palindrome Sum(差分)相关的知识,希望对你有一定的参考价值。
题目大意
??给一个长度为偶数且每个元素不大于(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(尺取法)