• cf 1167 E Range Deleting


    cf 1167 E. Range Deleting

    题意

    给出n个x范围的数,求删除范围在[L, R]的数,使得该序列成为一个非严格递增的序列,问有多少对数?(注空序列也算进答案,即[1,x]也是答案

    题解

    1.可以看出,如果删除[1, i]是符合题意的答案,那么[1, i+1] ~ [1, x]都是符合题意的答案。

    2.如果[1, i]不是合法的,那么[2, i]也不可能是合法的。所以左右指针都只会往前移;

    3.如果[L, R]是合法的,那么答案贡献是 x - R + 2;

    判断区间[L, R]是否合法的:

    [1, L-1]的数最靠后的位置 < [R + 1, x]的数最靠前的位置

    下面继续捋一捋怎么写代码:

    先找出最小的i,满足[1, i]是合法的。
    把左指针往前移,如果[2, i]不合法,就把右指针往后移,直到合法!
    如果i最靠前的位置 > [1, i - 1]最靠后的位置,说明左指针往后移也不可能出现合法的了。
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using std::max;
    using std::min;
    
    int l[1000010], ll[1000010], r[1000010], rr[1000010];
    int main() {
        int n, x, a;
        scanf("%d %d", &n, &x);
        memset(l, 0x3f3f3f3f, sizeof(l));
        memset(ll, 0x3f3f3f3f, sizeof(ll));
        for(int i = 1; i <= n; i++) {
            scanf("%d", &a);
            l[a] = min(i, l[a]);
            r[a] = i;
        }
        for(int i = 1; i <= x; i++) {
            rr[i] = max(rr[i-1], r[i]);//rr记录[1, i]最靠后的位置
            ll[x - i + 1] = min(l[x - i + 1], ll[x - i + 2]);//ll记录[i, x]最靠前的位置
        }
        int R = x;
        long long ans = 0;
        while(ll[R] >= r[R-1] && R >= 1) R--;//算出最小的i
        for(int i = 0; i < x; i++) {
            if(i && l[i] < rr[i-1]) break;//i最靠前的位置>[1, i - 1]最靠后的位置
            while(R <= i + 1 || rr[i] > ll[R]) R++;//右指针往后移,直到找到合法的区间,
            ans += x - R + 2;
        }
        printf("%lld
    ", ans);
        return 0;
    }
    
    
  • 相关阅读:
    LInux SSH远程文件/目录传输命令scp(转载)
    Linux系统时间设置(转载)
    Linux重置mysql密码(转载)
    快速输入(简单版)
    bitset
    或 、与、异或
    bitset
    Java面向对象3(K~O)
    Java面向对象2(G~J)
    数据结构实验之栈与队列六:下一较大值(二)(SDUT 3333)
  • 原文地址:https://www.cnblogs.com/fanshhh/p/11370669.html
Copyright © 2020-2023  润新知