ZOJ 3953:Intervals(优先队列+思维)

Posted Shadowdsp

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ZOJ 3953:Intervals(优先队列+思维)相关的知识,希望对你有一定的参考价值。

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5572

题意:给出n个线段,问最少删除几个线段可以使得任意一个点不会被三个以上的线段覆盖。

思路:首先离散化坐标。

然后想着按右端点从小到大排序后直接O(n)扫的贪心,但是后面发现错误了。

应该按左端点从小到大排序,然后用一个优先队列(按右端点从大到小排序)。

开始扫坐标,当有与该坐标相同的点的左端点就进队,用ed[]记录右端点的位置。

用cnt记录当前这个点有多少个区间覆盖,当cnt>=3的时候就出队更新。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define N 50010
 4 struct node {
 5     int l, r, id;
 6     node () {}
 7     node (int l, int r, int id) : l(l), r(r), id(id) {}
 8     bool operator < (const node &rhs) const {
 9         if(r != rhs.r) return r < rhs.r;
10         return l < rhs.l;
11     }
12 } seg[N];
13 vector<int> ans;
14 priority_queue<node> que;
15 int ed[N*2], p[N*2];
16 bool cmp(const node &a, const node &b) {
17     if(a.l != b.l) return a.l < b.l;
18     return a.r < b.r;
19 }
20 int main() {
21     int t; scanf("%d", &t);
22     while(t--) {
23         int n, u, v; scanf("%d", &n);
24         ans.clear(); memset(ed, 0, sizeof(ed));
25         while(!que.empty()) que.pop();
26         int cnt = 0, now = 0, num = 0;
27         for(int i = 0; i < n; i++) scanf("%d%d", &u, &v), seg[i] = node(u, v, i + 1), p[cnt++] = u, p[cnt++] = v;
28         sort(seg, seg + n, cmp); sort(p, p + cnt);
29         cnt = unique(p, p + cnt) - p;
30         for(int i = 0; i < n; i++)
31             seg[i].l = lower_bound(p, p + cnt, seg[i].l) - p,
32             seg[i].r = lower_bound(p, p + cnt, seg[i].r) - p;
33 
34         for(int i = 0; i < cnt && now < n; i++) {
35             while(seg[now].l == i && now < n) {
36                 num++;
37                 ed[seg[now].r + 1]++; // 线段的终点
38                 que.push(seg[now++]);
39             }
40             num -= ed[i]; // 离开了某线段的范围
41             while(num >= 3) {
42                 node tmp = que.top(); que.pop();
43                 num--; ed[tmp.r + 1]--; // 这个线段被删除
44                 ans.push_back(tmp.id);
45             }
46         }
47         printf("%d\n", ans.size()); sort(ans.begin(), ans.end());
48         for(int i = 0; i < ans.size(); i++) printf("%d%c", ans[i], i + 1 == ans.size() ? \n :  );
49     }
50     return 0;
51 }

 

以上是关于ZOJ 3953:Intervals(优先队列+思维)的主要内容,如果未能解决你的问题,请参考以下文章

ZOJ 3632 ----dp+优先队列

ZOJ 3230 Solving the Problems(数学 优先队列啊)

zoj 4120Tokens on the Segments(优先队列+贪心)

ZOJ2724_Windows Message Queue(STL/优先队列)

ZOJ 3888 Twelves Monkeys (预处理+优先队列)

ZOJ - 4109 - Welcome Party (并查集 + BFS + 优先队列)