码迷,mamicode.com
首页 > 其他好文 > 详细

CF961E Tufurama 主席树

时间:2018-10-19 23:49:19      阅读:356      评论:0      收藏:0      [点我收藏+]

标签:line   name   algorithm   void   ima   str   get   min   style   

技术分享图片

对原问题进行转化

考虑对每个$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 = \n) {
        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;
}

 

CF961E Tufurama 主席树

标签:line   name   algorithm   void   ima   str   get   min   style   

原文地址:https://www.cnblogs.com/reverymoon/p/9819282.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!