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 }

 

posted @ 2016-03-26 18:48  Recoder  阅读(218)  评论(0编辑  收藏  举报