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
1≤T≤5
1≤N≤105
0≤a<b≤109Output 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\n", cas++, ans); 108 } 109 110 return 0; 111 }
posted on 2015-04-14 20:25 Stomach_ache 阅读(312) 评论(0) 编辑 收藏 举报
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 智能桌面机器人:用.NET IoT库控制舵机并多方法播放表情
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 手把手教你在本地部署DeepSeek R1,搭建web-ui ,建议收藏!
· 新年开篇:在本地部署DeepSeek大模型实现联网增强的AI应用
· 程序员常用高效实用工具推荐,办公效率提升利器!
· Janus Pro:DeepSeek 开源革新,多模态 AI 的未来
· 【译】WinForms:分析一下(我用 Visual Basic 写的)