Codeforces Round #216 (Div. 2) E. Valera and Queries 树状数组 离线处理

题意:n个线段[Li, Ri], m次询问, 每次询问由cnt个点组成,输出包含cnt个点中任意一个点的线段的总数。

由于是无修改的,所以我们首先应该往离线上想, 不过我是没想出来。

首先反着做,先求不包含这个cnt个点的线段的总数, 那么不包含这些点的线段必然在cnt个点之间(这里需要再加两个点一个是0, 一个是MAX),

我们可以把所有线段按R分类, 然后按右端点遍历,对于当前的线段可以在Li 处+1, 然后对于每一次询问中两个点(x, y)之间线段的个数,

只需要查询 左端点大于等于x的个数就好了,这里因为是按右端点从小到大遍历的,所以不用考虑用端点了。

发现, 大多数的离线处理都是先把其中的一维从小到大排序, 然后处理另一维。 这样相当于降维。

 1 #include <bits/stdc++.h>
 2 
 3 const int maxn = 1e6 + 10;
 4 typedef std::pair <int, int> pii;
 5 std::vector <int> seg[maxn], q[maxn];
 6 std::vector <pii> rq[maxn];
 7 namespace FenwickTree{
 8     int arr[maxn];
 9     void inc(int x, int d){
10         while (x < maxn){
11             arr[x] += d;
12             x += x & -x;
13         }
14     }
15     int query(int x){
16         int res = 0;
17         while (x > 0){
18             res += arr[x];
19             x -= x & -x;
20         }
21         return res;
22     }
23     int query(int ua, int ub){
24         return query(ub) - query(ua-1);
25     }
26 }
27 int ans[maxn];
28 void init(){
29     memset(ans, 0, sizeof (ans));
30     for (int i = 0; i < maxn; i++){
31         seg[i].clear();
32         q[i].clear();
33         rq[i].clear();
34     }
35 }
36 int main()
37 {
38     #ifndef ONLINE_JUDGE
39         freopen("in.txt", "r", stdin);
40     #endif // ONLINE_JUDGE
41     int n, m;
42     while (~ scanf ("%d%d", &n, &m)){
43         init();
44         for (int i = 0; i < n; i++){
45             int ua, ub;
46             scanf("%d%d", &ua, &ub);
47             ua++, ub++;
48             seg[ub].push_back(ua);
49         }
50         for (int i = 0; i < m; i++){
51             int cnt, p;
52             scanf ("%d", &cnt);
53             q[i].push_back(1);
54             while (cnt--){
55                 scanf ("%d", &p);
56                 p++;
57                 q[i].push_back(p);
58             }
59             q[i].push_back(maxn-1);
60             for (int j = 0; j < q[i].size()-1; j++){
61                 int ua = q[i][j]+1;
62                 int ub = q[i][j+1]-1;
63                 rq[ub].push_back(std::make_pair(ua, i));
64             }
65         }
66         for (int i = 1; i < maxn; i++){
67             for (int j = 0; j < seg[i].size(); j++){
68                 int tmp = seg[i][j];
69                 FenwickTree::inc(seg[i][j], 1);
70             }
71             for (int j = 0; j < rq[i].size(); j++){
72                 int idx = rq[i][j].second;
73                 int tmp = rq[i][j].first;
74                 ans[idx] += FenwickTree::query(rq[i][j].first, i);
75             }
76         }
77         for (int i = 0; i < m; i++){
78             printf("%d\n", n - ans[i]);
79         }
80     }
81     return 0;
82 }

 

posted @ 2015-10-08 14:14  PlasticSpirit  阅读(255)  评论(0编辑  收藏  举报