Educational Codeforces Round 10 D. Nested Segments (树状数组)
题目链接:http://codeforces.com/problemset/problem/652/D
给你n个不同的区间,L或者R不会出现相同的数字,问你每一个区间包含多少个区间。
我是先把每个区间看作整体,按照R从小到大排序。然后从最小的R开始枚举每个区间,要是枚举到这个区间L的时候,计算之前枚举的区间有多少个Li在L之后,那么这些Li大于L的区间的数量就是答案。那我每次枚举的时候用树状数组add(L , 1) 说明在L这个位置上出现了区间,之后枚举的时候计算L之前的和,然后i - 1 - sum(L)这个就是答案。(跟用树状数组计算逆序对有点类似,自己模拟一下就明白了)。
但是区间的L和R很大,区间的个数又不是很多。所以我用离散化,区间的大小包含1到2n这些数。我用map做的,也可以用二分。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <map> 6 using namespace std; 7 const int MAXN = 4e5 + 10; 8 struct data { 9 int l , r , pos; 10 }a[MAXN]; 11 int ans[MAXN] , n , bit[MAXN] , x[MAXN * 2]; 12 map <int , int> mp; 13 bool cmp(data x , data y) { 14 return x.r < y.r; 15 } 16 int sum(int i) { 17 int s = 0; 18 while(i > 0) { 19 s += bit[i]; 20 i -= (i&-i); 21 } 22 return s; 23 } 24 25 void add(int i , int x) { 26 while(i <= n*2) { 27 bit[i] += x; 28 i += (i&-i); 29 } 30 } 31 32 int main() 33 { 34 scanf("%d" , &n); 35 int cont = 0; 36 for(int i = 1 ; i <= n ; i++) { 37 scanf("%d %d" , &a[i].l , &a[i].r); 38 x[++cont] = a[i].l; 39 x[++cont] = a[i].r; 40 a[i].pos = i; 41 } 42 sort(x + 1 , x + cont + 1); 43 for(int i = 1 ; i <= cont ; i++) { 44 mp[x[i]] = i; 45 } 46 sort(a + 1 , a + n + 1 , cmp); 47 for(int i = 1 ; i <= n ; i++) { 48 a[i].l = mp[a[i].l]; 49 a[i].r = mp[a[i].r]; 50 } 51 for(int i = 1 ; i <= n ; i++) { 52 ans[a[i].pos] = i - 1 - sum(a[i].l); 53 //cout << a[i].l << " " << a[i].r << " " << sum(a[i].l) << endl; 54 add(a[i].l , 1); 55 } 56 for(int i = 1 ; i <= n ; i++) { 57 printf("%d\n" , ans[i]); 58 } 59 }