对原问题进行转化
考虑对每个$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; }