Touching segments(数据结构)

题目链接

Problem Statement

Your Maths professor is a very nice guy, but he sometimes comes up with not so funny tasks. Today is one such day. The professor drew a bunch of parallel line segments on the board and asked the following question: "How many of these segments can be touched, even on their edges, by exactly two lines perpendicular to them?"

After a few seconds, he spoke again: "Let's make it more interesting. I will give you the starting and the ending points of N segments over the X's axis; today's homework will be to answer the question I asked you above for any set of such segments". Right after the professor's words, one guy asked: "Is there any restriction over the segments' location?", and the professor replied: "Not really, they are just segments, so they can overlap in all the ways you may imagine."

Everybody started thinking of the weird and unexpected task, without getting a convincing result. Some time later, the class got over and before leaving the classroom, the professor said: "Just to take this to the ultimate limits, your final qualification will depend entirely on this task. Good luck and please, don't try to cheat, I will know if you try to do so." So, that was it! Your final Maths qualification was hooked to some play on segments stuff.

Input Format

Input consists of several test cases. The first line in the input is an integer, T, denoting the number of test cases. T test cases follow, each one with the following format:

  • A single line with an integer, N, denoting the number of segments.

  • N lines, each defining a segment with two integers, a and b, separated by a single white space, meaning that there is a segment going from a to b.

Constraints
1T5 
1N105 
0a<b109

Output Format

For each test case the output should follow the following format:

  • A single line with "Case #: answer" (without the quotes) where # is the serial number of the current test case (start the numbering by 1) and answer is the maximum number of segments you can touch as described above.

See the sample output for more details.

Sample Input

4
5
2 3
1 3
1 5
3 4
4 5
5
1 2
1 3
2 3
1 4
1 5
4
1 5
1 6
1 7
8 10
3
1 2
3 4
5 6

Sample Output

Case 1: 5
Case 2: 5
Case 3: 4
Case 4: 2

Explanation

  • Case 1: We will draw two lines (parallel to Y-axis) crossing X-axis at point 2 and 4. These two lines will touch all the five segments.
  • Case 2: We can touch all the points even with one line crossing X-axis at 2.
  • Case 3: We will draw first line at any point in range [1,5] so that it can touch first three lines. We will draw second line crossing X-axis at any of the points in range [8,10] and it will touch the last line.
  • Case 4: It is not possible to touch more than two lines in this case.

好题一枚。

AC代码:

  1 #include <cmath>
  2 #include <cstdio>
  3 #include <vector>
  4 #include <cstring>
  5 #include <iostream>
  6 #include <algorithm>
  7 using namespace std;
  8 
  9 const int MAX_N = 200010;
 10 
 11 struct SegTree {
 12     int val[MAX_N << 2], lzy[MAX_N << 2];
 13     #define lson(x) (x<<1) 
 14     #define rson(x) ((x<<1) | 1)
 15     
 16     void build() {
 17         memset(val, 0, sizeof(val));
 18         memset(lzy, 0, sizeof(lzy));
 19     }
 20     
 21     void pushDown(int rt) {
 22         if (lzy[rt]) {
 23             val[lson(rt)] += lzy[rt];
 24             lzy[lson(rt)] += lzy[rt];
 25             val[rson(rt)] += lzy[rt];
 26             lzy[rson(rt)] += lzy[rt];
 27             lzy[rt] = 0;
 28         }
 29     }
 30     
 31     void pushUp(int rt) {
 32         val[rt] = max(val[lson(rt)], val[rson(rt)]);
 33     }
 34     
 35     void update(int rt, int l, int r, int ql, int qr, int v) {
 36         if (l >= ql && r <= qr) {
 37             val[rt] += v;
 38             lzy[rt] += v;
 39         } else {
 40             pushDown(rt);
 41             int mid = (l + r) >> 1;
 42             if (ql <= mid) update(lson(rt), l, mid, ql, qr, v);
 43             if (qr  > mid) update(rson(rt), mid+1, r, ql, qr, v);
 44             pushUp(rt);
 45         }
 46     }
 47     
 48     int query(int rt, int l, int r, int ql, int qr) {
 49         if (l >= ql && r <= qr) {
 50             return val[rt];
 51         } else {
 52             pushDown(rt);
 53             int mid = (l + r) >> 1;
 54             int res = 0;
 55             if (ql <= mid) res = max(res, query(lson(rt), l, mid, ql, qr));
 56             if (qr  > mid) res = max(res, query(rson(rt), mid+1, r, ql, qr));
 57             return res;
 58         }
 59     }
 60     
 61 }st;
 62 
 63 int l[MAX_N], r[MAX_N];
 64 int ll[MAX_N], rr[MAX_N];
 65 vector<int> b[MAX_N], e[MAX_N]; // segments begins at $i or ends at $i
 66 
 67 int main(void) {
 68     int T, cas = 1;
 69     scanf("%d", &T);
 70     while (T--) {
 71         int N;
 72         scanf("%d", &N);
 73         vector<int> arr;
 74         for (int i = 0; i < N; i++) {
 75             scanf("%d %d", l+i, r+i);
 76             arr.push_back(l[i]);
 77             arr.push_back(r[i]);
 78         }
 79         
 80         sort(begin(arr), end(arr));
 81         int m = unique(arr.begin(), arr.end()) - arr.begin();
 82         for (int i = 0; i < m; i++) {
 83             b[i].clear(); e[i].clear();
 84         }
 85         
 86         st.build();
 87         for (int i = 0; i < N; i++) {
 88             ll[i] = lower_bound(begin(arr), begin(arr)+m, l[i]) - begin(arr);
 89             rr[i] = lower_bound(begin(arr), begin(arr)+m, r[i]) - begin(arr);
 90             b[ll[i]].push_back(i);
 91             e[rr[i]].push_back(i);
 92             st.update(1, 0, m-1, ll[i], rr[i], 1);
 93         }
 94         
 95         int cnt = 0, ans = 0;
 96         for (int i = 0; i < m; i++) {
 97             for (const int &it : b[i]) {
 98                 st.update(1, 0, m-1, ll[it], rr[it], -1);
 99                 ++cnt;
100             }
101             ans = max(ans, cnt + st.query(1, 0, m-1, 0, m-1));
102             for (const int &it : e[i]) {
103                 st.update(1, 0, m-1, ll[it], rr[it], -1);
104                 --cnt;
105             }
106         }
107         printf("Case %d: %d
", cas++, ans);
108     }
109     
110     return 0;
111 }
View Code
原文地址:https://www.cnblogs.com/Stomach-ache/p/4425962.html