• cf 1443 D. Extreme Subtraction


    传送门
    感觉这题好棒啊,我就是想不到,如果没有看题解,我可能想个10年也想不出来。
    就是给出n个数字,你需要进行操作,任意替换一个数字,变成([1:k]),然后使得最后满足(a[i] + a[n - i + 1])都相等。
    求最小操作次数。

    看了一眼以为是三分的。以为看见题目里的x,想着枚举x。
    但是差分可以解决,就是对于每个(i in[1,frac{n}{2}])(a[i] + a[n - i + 1])的贡献值为0,表示可以到达,然后更改1次的区间的贡献值+1,更改2次的区间贡献值+2,注意的是三个区间不能够有并的关系就行了。然后分类讨论进行差分。最后求下前缀和,取最小值

    int a[N], b[N];
    int n, k;
    void change(int l, int r, int pos, int c){
        if(r == l) {
            if(l != pos) b[l] += c, b[l + 1] -= c;
            return;
        }
        if(l <= pos && pos <= r) {
            if(pos == l) b[l + 1] += c, b[r + 1] -= c;
            else if(pos == r) b[l] += c, b[r] -= c;
            else {
                if(r - l + 1 >= 3) {
                    b[l] += c, b[pos] -= c;
                    b[pos + 1] += c, b[r + 1] -= c;
                }
            }
        }else b[l] += c, b[r + 1] -= c;
    }
    void solve(int kase){
        _(n), _(k);
        for(int i = 1; i <= n; i++) _(a[i]);
        for(int i = 0; i <= 2 * k + 2; i++) b[i] = 0;
        for(int i = 1; i <= n / 2; i++) {
            int mi = min(a[i], a[n - i + 1]);
            int mx = max(a[i], a[n - i + 1]);
            int lone = 1 + mi, rone = mx + k;
            int ltwo = 2, rtwo = 2 * k;
            int now = a[i] + a[n - i + 1];
            change(lone, rone, now, 1);
            if(lone != 2) {
                change(ltwo, lone - 1, now, 2);
            }
            if(rone != 2 * k) {
                change(rone + 1, rtwo, now, 2);
            }
        }
        int ans = INF, now = 0;
        for(int i = 1; i <= 2 * k; i++) b[i] += b[i - 1];
        for(int i = 2; i <= 2 * k; i++)
            ans = min(ans, b[i]);
        printf("%d
    ", ans);
    }
    
  • 相关阅读:
    手动去除迅雷7广告
    MIPS学习笔记
    龙芯中断系统
    《ecos增值包》之FAT文件系统篇
    MIPS架构学习笔记
    【3D数学】之向量
    【温故Delphi】之窗口ShowModal
    【Manage It】之项目规划
    【3D数学】之坐标系
    【Manage It】之启动项目
  • 原文地址:https://www.cnblogs.com/Emcikem/p/14254902.html
Copyright © 2020-2023  润新知