zoukankan      html  css  js  c++  java
  • Constant Palindrome Sum

    Constant Palindrome Sum

    Constant Palindrome Sum 题目链接

    思路

    由于每一个数字的取值范围是([1, k]),所以对与每一对数字的和的取值应该在([2, 2k])

    对于每一对数字我们可以选择改变一个、改变两个或者一个都不改变。

    • 改变一个的时候,数值区域可以变成([min(a, b) + 1, max(a, b) + k])

    • 改变两个的时候,数值区域可以变成([2, min(a, b)]),和([max(a, b) + k + 1, 2k])

    • 一个都不变,其值只有可能是(a + b)

    我们定义三个数组

    • 1、num数组,记录的是下标为 ((a + b))的数对的个数。

    • 2、change1数组,记录的是改变一个数字的时候可取的区域相应的操作数,这里为了降低复杂度所以采用差分的形式,大致操作如下
      (change1[min(a, b) + 1]++)
      (change1[max(a, b) + k + 1]--)

    • 3、change2数组,记录的是改变两个数字对应的操作次数,其对应对change2数组的操作如下
      (change2[2] += 2,change2[min(a, b) + 1] -= 2)
      (change2[max(a, b) + k + 1] += 2,change2[2k + 1] -= 2)

    所以最后的答案就是当前答案操作一次的数量加上操作两次的数量减去当前答案的数值的数量

    也就是 (change1[i] + change2[i] - num[i])

    减去 (num[i]) 的操作相信大家应该明白,就是在
    ([min(a, b) + 1, max(a, b) + k]) 中包括了 (a + b)

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 4e5 + 10;
    const int INF = 0x3f3f3f3f;
    int a[N], num[N], change1[N], change2[N], n, m;
    int main() {
        // freopen("in.txt", "r", stdin);
        int t;
        scanf("%d", &t);
        while(t--) {
            scanf("%d %d", &n, &m);
            for(int i = 1; i <= n; i++)
                scanf("%d", &a[i]);
            for(int i = 0; i <= 2 * m + 5; i++)
                num[i] = change1[i] = change2[i] = 0;
            //所有和的可能性[2, 2m]
            for(int i = 1; i <= n / 2; i++) {
                num[a[i] + a[n - i + 1]]++;
                int l = min(a[i], a[n - i + 1]) + 1;
                int r = max(a[i], a[n - i + 1]) + m;
                //[l, r]只要改变一个数
                change1[l]++, change1[r + 1]--;
                //[2, l - 1] 和 [r + 1, 2m]改变两个数。
                change2[2] += 2, change2[l]-= 2;
                change2[r + 1] += 2;
            }
            for(int i = 3; i <= 2 * m + 5; i++) {
                // num[i] += num[i - 1];
                change1[i] += change1[i - 1];
                change2[i] += change2[i - 1];
            }
            // for(int i = 2; i <= 2 * m; i++) {
            //     printf("%d ", num[i]);
            // }
            // puts("");
            // for(int i = 2; i <= 2 * m; i++) {
            //     printf("%d ", change1[i]);
            // }
            // puts("");
            // for(int i = 2; i <= 2 * m; i++) {
            //     printf("%d ", change2[i]);
            // }
            // puts("");
            int ans = INF;
            for(int i = 2; i <= 2 * m; i++)
                ans = min(ans, change1[i] - num[i] + change2[i]);
            printf("%d
    ", ans);
        }
        return 0;
    }
    
  • 相关阅读:
    洛谷P4016 负载平衡问题 费用流
    Reactor Cooling ZOJ
    Acme Corporation UVA
    洛谷P4014 分配问题 费用流
    洛谷P4013 数字梯形问题 费用流
    洛谷P4012 深海机器人问题 费用流
    力扣题目汇总(旋转数字,移除元素,找不同)
    力扣题目汇总(两数之和Ⅱ-输入有序数组,删除排序数组中的重复项,验证回文串)
    逻辑练练手小程序
    爬虫之Scarpy.Request
  • 原文地址:https://www.cnblogs.com/lifehappiness/p/12802598.html
Copyright © 2011-2022 走看看