• Codeforces 815D Karen and Cards 线段树 || 容斥 (看题解)


    Karen and Cards

    刚开始想的是容斥, 但是感觉不太好容斥, 然后就gun去看题解了。。

    我们考虑枚举 a , n张排分成两种 >= a 和 < a,然后我们把后两维看成平面上的点, 考虑哪些点会受到

    限制, 对于 >= a 的卡片来说, 受限制区域为整个区域减去右上角矩形, 对于 < a的卡片来说, 受限制区域为

    左下角矩形, 定义f(b)为第二位为 b 使 c 受限制的最大值, 首先发现 f 函数是单调的, 一张卡片从 < a 转变到 >= a很好修改,

    所以我们从大到小枚举 a 用线段树去统计在答案。

    容斥的话可以看这个。。

    https://codeforces.com/contest/815/submission/27860187

    感觉有点巧妙。

    #include<bits/stdc++.h>
    #define LL long long
    #define LD long double
    #define ull unsigned long long
    #define fi first
    #define se second
    #define mk make_pair
    #define PLL pair<LL, LL>
    #define PLI pair<LL, int>
    #define PII pair<int, int>
    #define SZ(x) ((int)x.size())
    #define ALL(x) (x).begin(), (x).end()
    #define fio ios::sync_with_stdio(false); cin.tie(0);
    
    using namespace std;
    
    const int N = 5e5 + 7;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const int mod = 998244353;
    const double eps = 1e-8;
    const double PI = acos(-1);
    
    template<class T, class S> inline void add(T& a, S b) {a += b; if(a >= mod) a -= mod;}
    template<class T, class S> inline void sub(T& a, S b) {a -= b; if(a < 0) a += mod;}
    template<class T, class S> inline bool chkmax(T& a, S b) {return a < b ? a = b, true : false;}
    template<class T, class S> inline bool chkmin(T& a, S b) {return a > b ? a = b, true : false;}
    
    int n, p, q, r;
    int a[N], b[N], c[N];
    int id[N], limit[N];
    LL ans;
    
    #define lson l, mid, rt << 1
    #define rson mid + 1, r, rt << 1 | 1
    struct segmentTree {
        LL sum[N << 2]; int lazy[N << 2], mn[N << 2], mx[N << 2];
        inline void pull(int rt) {
            sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
            mx[rt] = max(mx[rt << 1], mx[rt << 1 | 1]);
            mn[rt] = min(mn[rt << 1], mn[rt << 1 | 1]);
        }
        inline void push(int rt, int l, int r) {
            if(~lazy[rt]) {
                int mid = l + r >> 1;
                sum[rt << 1] = 1LL * (mid - l + 1) * lazy[rt];
                sum[rt << 1 | 1] = 1LL * (r - mid) * lazy[rt];
                lazy[rt << 1] = lazy[rt << 1 | 1] = lazy[rt];
                mx[rt << 1] = mn[rt << 1] = lazy[rt];
                mx[rt << 1 | 1] = mn[rt << 1 | 1] = lazy[rt];
                lazy[rt] = -1;
            }
        }
        void build(int l, int r, int rt) {
            lazy[rt] = -1;
            if(l == r) {
                sum[rt] = limit[l];
                mx[rt] = limit[l];
                mn[rt] = limit[l];
                return;
            }
            int mid = l + r >> 1;
            build(lson); build(rson);
            pull(rt);
        }
        void update(int L, int R, int val, int l, int r, int rt) {
            if(R < l || r < L || R < L) return;
            if(mn[rt] >= val) return;
            if(L <= l && r <= R && mx[rt] <= val) {
                sum[rt] = 1LL * (r - l + 1) * val;
                mx[rt] = val;
                mn[rt] = val;
                lazy[rt] = val;
                return;
            }
            if(l == r) return;
            push(rt, l, r);
            int mid = l + r >> 1;
            update(L, R, val, lson);
            update(L, R, val, rson);
            pull(rt);
        }
    } Tree;
    
    
    int main() {
        scanf("%d%d%d%d", &n, &p, &q, &r);
        for(int i = 1; i <= n; i++) {
            scanf("%d%d%d", &a[i], &b[i], &c[i]);
            id[i] = i;
        }
        sort(id + 1, id + 1 + n, [&](int x, int y) {
            return a[x] > a[y];
        });
        for(int i = 1; i <= n; i++) chkmax(limit[b[i]], c[i]);
        for(int i = q; i >= 1; i--) chkmax(limit[i], limit[i + 1]);
        Tree.build(1, q, 1);
        for(int i = p, j = 1; i >= 1; i--) {
            while(j <= n && a[id[j]] >= i) {
                Tree.update(1, b[id[j]], r, 1, q, 1);
                Tree.update(b[id[j]] + 1, q, c[id[j]], 1, q, 1);
                j++;
            }
            ans += 1LL * q * r - Tree.sum[1];
        }
        printf("%lld
    ", ans);
        return 0;
    }
    
    /*
    */
  • 相关阅读:
    [haoi2011]向量
    [haoi2008]硬币购物
    noi2001 [食物链]并查集p1697
    [haoi2012]容易题(数论+容斥的思想)
    p1620田忌赛马(贪心+模拟)
    p1368[扑街]广场铺砖
    [zjoi2010]网络扩容
    是时候写一篇总结了
    P1630 求和
    魔术棋子
  • 原文地址:https://www.cnblogs.com/CJLHY/p/11039180.html
Copyright © 2020-2023  润新知