zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    《Excel效率手册:早做完,不加班》
    《“胡”说IC——菜鸟工程师完美进阶》
    《UNIX环境高级编程(第3版)》
    《学习R》
    《Netty权威指南》
    《啊哈!算法》
    《流程的永恒之道》
    《算法帝国》
    Guava-Optional可空类型
    guava之Joiner 和 Splitter
  • 原文地址:https://www.cnblogs.com/Stomach-ache/p/4425962.html
Copyright © 2011-2022 走看看