【CF961E】Tufurama

E.
        Tufurama
time
        limit per test
2
        seconds
memory
        limit per test
256
        megabytes
input
        
standard
        input
output
        
standard
        output
One
        day Polycarp
        decided to rewatch his absolute favourite episode of well-known TV series
        "Tufurama". He was pretty surprised when he got results only for
        season 7 episode 3 with his search query of "Watch Tufurama season 3
        episode 7 online full hd free". This got Polycarp confused — what if he
        decides to rewatch the entire series someday and won't be able to find the
        right episodes to watch? Polycarp now wants to count the number of times he
        will be forced to search for an episode using some different method.
TV
        series
        have n seasons
        (numbered 1 through n),
        the i-th
        season has ai episodes
        (numbered 1 through ai).
        Polycarp thinks that if for some pair
        of integers x and y (x < y)
        exist both season x episode y and
        season y episode x then
        one of these search queries will
        include the wrong results. Help Polycarp to calculate the number of such pairs!
Input
            
The
        first line
        contains one integer n (1  ≤ n  ≤  2·105) —
        the
        number of seasons.
The
        second line
        contains n integers
        separated by space a1, a2, ..., an (1 ≤ ai ≤ 109) —
        number
        of episodes in each season.
Output
            
Print
        one
        integer — the number of pairs x and y (x < y)
        such that
        there exist both season x episode y and
        season y episode x.
        
Examples
            
input
            
5
1 2 3 4 5
1 2 3 4 5
output
            
0
        
input
            
3
8 12 7
8 12 7
output
            
3
        
input
            
3
3 2 1
3 2 1
output
            
2
        
Note
            
Possible
        pairs
        in the second example:
1.  
            
    x = 1, y = 2 (season
        1 episode 2 
            
            
             season 2 episode 1);
2.  
            
    x = 2, y = 3 (season
        2 episode 3 
            
            
             season 3 episode 2);
3.  
            
    x = 1, y = 3 (season
        1 episode 3 
            
            
             season 3 episode 1).
In
        the third
        example:
1.  
            
    x = 1, y = 2 (season
        1 episode 2 
            
            
             season 2 episode 1);
2.  
            
    x = 1, y = 3 (season
        1 episode 3 
            
            
             season 3 episode 1).
题目大意:

- 1) i < j
 - 2) a[i] >= j
 - 3) a[j] >=i
 
显然地,大于 n 的 a[i] 可舍弃
对于给定的 j 位置,i < j 且 i <= a[j]
故 i ∈ [1, min(j - 1, a[j]]
为了满足 a[i] >= j,即求对于 i ∈ [1, min(j - 1, a[j]],a[i] >= j 的个数
用个树状数组维护
using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; namespace _c { c double pi = acos(-1.0); namespace min { c int i8 = -128; c int i16 = -32768; c int i = -2147483647 - 1; c ll l = -9223372036854775807LL - 1; } // namespace min namespace max { c int i8 = 127; c int i16 = 32767; c int i = 2147483647; c ll l = 9223372036854775807LL; } // namespace max } // namespace _c namespace _f { template <typename T> inline c T gcd(T m, T n) { while (n != 0) { T t = m % n; m = n; n = t; } return m; } template <typename T> inline c T abs(c T &a) { return a > 0 ? a : -a; } template <typename T> inline T pow(T a, T b) { T res = 1; while (b > 0) { if (b & 1) { res = res * a; } a = a * a; b >>= 1; } return res; } template <typename T> inline T pow(T a, T b, c T &m) { a %= m; T res = 1; while (b > 0) { if (b & 1) { res = res * a % m; } a = a * a % m; b >>= 1; } return res % m; } } // namespace _f namespace io { template <typename T> inline T read() { r T res = 0, neg = 1; char g = getchar(); for (; !isdigit(g); g = getchar()) { if (g == '-') { neg = -1; } } for (; isdigit(g); g = getchar()) { res = res * 10 + g - '0'; } return res * neg; } template <typename T> inline void read(T &t) { t = read<T>(); } template <typename T> inline void readln(c T first, c T last) { for (r T it = first; it != last; it++) { read(*it); } } template <typename T> inline void _write(T x) { if (x < 0) { putchar('-'); x = -x; } if (x > 9) { _write(x / 10); } putchar(x % 10 + '0'); } template <typename T> inline void write(c T &x, c char &sep = ' ') { _write(x); putchar(sep); } template <typename T> inline void writeln(c T &x) { write(x, '\n'); } template <typename T> inline void writeln(c T first, c T last, c char &sep = ' ', c char &ends = '\n') { for (r T it = first; it != last; it++) { write(*it, sep); } putchar(ends); } template <typename T, typename... Args> void read(T &x, Args &... args) { read(x); read(args...); } } // namespace io typedef ll used_type; int n; const int N = 2e5 + 5; used_type ans; used_type p[N]; vector<used_type> d[N]; inline used_type lowbit(used_type x) { return x & (-x); } int main() { io::read(n); for (register int i = 1, a; i <= n; i++) { a = std::min(io::read<int>(), n); for (register int j = a; j > 0; j -= lowbit(j)) { ans += p[j]; } if (a > i) { for (register int j = i; j <= n; j += lowbit(j)) { p[j]++; } d[a].emplace_back(i); } for (const auto &x : d[i]) { for (register int j = x; j <= n; j += lowbit(j)) { p[j]--; } } } io::writeln(ans); }
这道题能想到树状数组维护的是魔鬼吧。。。
回复删除(还有值域线段树和 cdq 分治的做法,但是我不会
回复删除