(线段树+离散化)POJ 2528.Mayor's posters

来源:互联网 发布:js frame 高度 编辑:程序博客网 时间:2024/05/16 23:43

转载:http://notonlysuccess.me/?p=978


poj2528 Mayor’s posters
题意:在墙上贴海报,海报可以互相覆盖,问最后可以看见几张海报
思路:这题数据范围很大,直接搞超时+超内存,需要离散化:
离散化简单的来说就是只取我们需要的值来用,比如说区间[1000,2000],[1990,2012] 我们用不到[-∞,999][1001,1989][1991,1999][2001,2011][2013,+∞]这些值,所以我只需要1000,1990,2000,2012就够了,将其分别映射到0,1,2,3,在于复杂度就大大的降下来了
所以离散化要保存所有需要用到的值,排序后,分别映射到1~n,这样复杂度就会小很多很多
而这题的难点在于每个数字其实表示的是一个单位长度(并非一个点),这样普通的离散化会造成许多错误(包括我以前的代码,poj这题数据奇弱)
给出下面两个简单的例子应该能体现普通离散化的缺陷:
例子一:1-10 1-4 5-10
例子二:1-10 1-4 6-10
普通离散化后都变成了[1,4][1,2][3,4]
线段2覆盖了[1,2],线段3覆盖了[3,4],那么线段1是否被完全覆盖掉了呢?
例子一是完全被覆盖掉了,而例子二没有被覆盖

为了解决这种缺陷,我们可以在排序后的数组上加些处理,比如说[1,2,6,10]
如果相邻数字间距大于1的话,在其中加上任意一个数字,比如加成[1,2,3,6,7,10],然后再做线段树就好了.

代码实现结合自己的情况做了修改。

例如离散的方式:总是把输入的每个点的前后两个点都考虑进去。

#include <iostream>#include <cstdio>#include <cstring>#include <vector>#include <cmath>#include <algorithm>using namespace std;#define forr(i,f_start,f_end) for(int i=f_start;i<f_end;++i)#define mem(x,i) memset(x,i,sizeof(x))const int maxn = 10005*3;typedef long long LL;const int INF = 0xfffffff;int input(){int a;scanf("%d", &a);return a;}int Left[maxn], Right[maxn];int N;///---------------线段树------------------------#define lson l , m , rt << 1#define rson m + 1 , r , rt << 1 | 1bool Hash[maxn];int col[maxn << 4];int cnt;/*PushDown的功能是:标记传递(此题标记为poster的编号)*/void PushDown(int rt) {if (col[rt] != -1) {col[rt << 1] = col[rt << 1 | 1] = col[rt];col[rt] = -1;}}/*update的功能是:用col[]实现"贴poster"*/void update(int L, int R, int c, int l, int r, int rt) {if (L <= l && r <= R) {col[rt] = c;return;}PushDown(rt);int m = (l + r) >> 1;if (L <= m) update(L, R, c, lson);if (m < R) update(L, R, c, rson);}void query(int l, int r, int rt) {if (col[rt] != -1) {if (!Hash[col[rt]]) cnt++;//Hash[]标记编号为col[rt]的poster是否已计数Hash[col[rt]] = true;return;}if (l == r) return;int m = (l + r) >> 1;query(lson);query(rson);}///---------------线段树------------------------int compress(int x1[], int x2[]){//int xs[maxn], topxs++;vector<int> xs;for (int i = 0; i < N; i++){for (int delta = -1; delta <= 1; delta++){xs.push_back(x1[i]+delta);xs.push_back(x2[i]+delta);}}sort(xs.begin(), xs.end());xs.erase(unique(xs.begin(), xs.end()), xs.end());for (int i = 0; i < N; i++){x1[i] = lower_bound(xs.begin(), xs.end(), x1[i]) - xs.begin();x2[i] = lower_bound(xs.begin(), xs.end(), x2[i]) - xs.begin();}return xs.size();}void solve(){int CP = compress(Left, Right);mem(col, -1);for (int i = 0; i < N; i++){update(Left[i], Right[i], i, 0, CP - 1, 1);}mem(Hash, false);cnt = 0;query(0, CP - 1, 1);printf("%d\n", cnt);}int main(){//freopen("f:\\input.txt", "r", stdin);for (int T = input(); T--;){N = input();for (int i = 0; i < N; i++)scanf("%d%d", &Left[i], &Right[i]);solve();}return 0;}


0 0
原创粉丝点击