CF961E Tufurama 树状数组
E. Tufurama
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!
The first line contains one integer n (1 ≤ n ≤ 2·10^5) — the number of seasons.
The second line contains n integers separated by space a1, a2, ..., an (1 ≤ ai ≤ 10^9) — number of episodes in each season.
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.
题意:
有一部电视剧有n季,每一季有ai集。定义二元组(i,j):存在第i季有第j集。求(i,j)与(j,i)同时合法(i<j)的对数。
真实题意就是:求<i,j>对数,使得a[i]≥j,a[j]≥i并且(i<j)
BIT做法
像很多其他题一样,对于这样的、关于元素大小关系之间的限制的题目,先排个序总是能够解决个一维限制掉去的。
我们使用一个结构体node x,x.i表示季数;x.a表示该季的集数。首先对x.a排序。那么就变成这个样子:
p[].a(j) 3 5 1 2
p[].i(i) 1 2 3 4
|
|
p[].a(j) 1 2 3 4 (取min之后)
p[].i(i) 3 4 1 2
先考虑每次的统计,那么只要ans+=query(a[i])就可以了。意思就是说ans加上1..a[i]季的贡献(其中每一季的贡献要么是0要么是1,但是由于之后会有修改,所以我们用BIT维护)
now用来更新那些已经 过气 没有贡献的答案,这里「没有贡献的答案」指的是p[now].a<i的情况,就是p[now]的电视剧集数太小了,已经不会再有贡献了,由于p[i].a是单增的,因此now++,扫一遍即可。
代码:
1 //#include"bits/stdc++.h" 2 #include<sstream> 3 #include<iomanip> 4 #include"cstdio" 5 #include"map" 6 #include"set" 7 #include"cmath" 8 #include"queue" 9 #include"vector" 10 #include"string" 11 #include"cstring" 12 #include"time.h" 13 #include"iostream" 14 #include"stdlib.h" 15 #include"algorithm" 16 17 #define db double 18 #define ll long long 19 #define vec vector<ll> 20 #define mt vector<vec> 21 #define ci(x) scanf("%d",&x) 22 #define cd(x) scanf("%lf",&x) 23 #define cl(x) scanf("%lld",&x) 24 #define pi(x) printf("%d\n",x) 25 #define pd(x) printf("%f\n",x) 26 #define pl(x) printf("%lld\n",x) 27 //#define rep(i, x, y) for(int i=x;i<=y;i++) 28 #define rep(i, n) for(int i=0;i<n;i++) 29 const int N = 1e6 + 5; 30 const int mod = 1e9 + 7; 31 const int MOD = mod - 1; 32 const int inf = 0x3f3f3f3f; 33 const db PI = acos(-1.0); 34 const db eps = 1e-10; 35 using namespace std; 36 ll ans; 37 int n, now, a[N],bit[N]; 38 struct node { 39 int a, i; 40 bool operator<(node &xx) const { 41 return a < xx.a; 42 } 43 } p[N]; 44 int read() { 45 char ch = getchar(); 46 int ret = 0; 47 for (; !isdigit(ch); ch = getchar()); 48 for (; isdigit(ch); ch = getchar()) 49 ret = (ret << 3) + (ret << 1) + ch - 48; 50 return ret; 51 } 52 void add(int x, int c) { for (; x <= n + 1; x += x & -x)bit[x] += c; } 53 int sum(int x) { 54 int ret = 0; 55 for (; x; x -= x & -x) 56 ret += bit[x]; 57 return ret; 58 } 59 int main() { 60 n = read(); 61 now = 1; 62 for (int i = 1; i <= n; i++) 63 a[i] = min(read(), n), p[i].a = a[i], p[i].i = i, add(i, 1); 64 sort(p + 1, p + n + 1); 65 for (int i = 1; i <= n; i++) { 66 while (now <= n && p[now].a < i)add(p[now++].i, -1);//去掉无贡献的值 67 ans += sum(a[i]); 68 if (a[i] >= i) ans--;//(i,j) i=j的情况去掉 69 } 70 cout << ans / 2 << endl; 71 return 0; 72 }