• CF961E Tufurama 主席树


    对原问题进行转化

    考虑对每个$i$,询问在$j in [i + 1, a[i]]$中满足$a[j] geqslant i$的个数

    这样子可以做到不重不漏

    个数满足差分的性质,使用主席树来维护即可

    复杂度$O(n log n)$

    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    namespace remoon {
        #define ri register int
        #define ll long long
        #define tpr template <typename ra>
        #define rep(iu, st, ed) for(ri iu = st; iu <= ed; iu ++)
        #define drep(iu, ed, st) for(ri iu = ed; iu >= st; iu --)    
        #define gc getchar
        inline int read() {
            int p = 0, w = 1; char c = gc();
            while(c > '9' || c < '0') { if(c == '-') w = -1; c = gc(); }
            while(c >= '0' && c <= '9') p = p * 10 + c - '0', c = gc();
            return p * w;
        }
        int wr[50], rw;
        #define pc(iw) putchar(iw)
        tpr inline void write(ra o, char c = '
    ') {
            if(!o) pc('0');
            if(o < 0) o = -o, pc('-');
            while(o) wr[++ rw] = o % 10, o /= 10;
            while(rw) pc(wr[rw --] + '0');
            pc(c);
        }
        tpr inline void cmin(ra &a, ra b) { if(a > b) a = b; }
        tpr inline void cmax(ra &a, ra b) { if(a < b) a = b; } 
        tpr inline bool ckmin(ra &a, ra b) { return (a > b) ? a = b, 1 : 0; }
        tpr inline bool ckmax(ra &a, ra b) { return (a < b) ? a = b, 1 : 0; }
    }
    using namespace std;
    using namespace remoon;
    #define sid 10000050
    #define xid 200050
    
    ll ans;
    int n, id;
    int a[xid], rt[xid];
    int ls[sid], rs[sid], sz[sid];
    
    inline void insert(int &now, int pre, int l, int r, int v) {
        now = ++ id;
        ls[now] = ls[pre]; rs[now] = rs[pre]; 
        sz[now] = sz[pre] + 1;
        if(l == r) return;
        int mid = (l + r) >> 1;
        if(v <= mid) insert(ls[now], ls[pre], l, mid, v);
        else insert(rs[now], rs[pre], mid + 1, r, v);
    }
    
    inline int qry(int l, int r, int ql, int qr, int ml, int mr) {
        if(ml > r || mr < l) return 0;
        if(ml <= l && mr >= r) return sz[qr] - sz[ql];
        int mid = (l + r) >> 1;
        int ret = qry(l, mid, ls[ql], ls[qr], ml, mr);
        ret += qry(mid + 1, r, rs[ql], rs[qr], ml, mr);
        return ret;
    }
    
    int main() {
        n = read();
        rep(i, 1, n) a[i] = min(read(), n);
        rep(i, 1, n) insert(rt[i], rt[i - 1], 1, n, a[i]);
        rep(i, 1, n) if(i + 1 <= a[i])
        ans += qry(1, n, rt[i], rt[a[i]], i, n);
        write(ans);
        return 0;
    }
  • 相关阅读:
    看代码写程序
    NP
    一道神题
    找平方数
    凝视
    排队打水
    时间计算
    git客户端下载地址
    iOS GCD
    UIView 和 CALayer的那点事
  • 原文地址:https://www.cnblogs.com/reverymoon/p/9819282.html
Copyright © 2020-2023  润新知