POJ 2528 Mayor's posters(线段树染色+离散化)
来源:互联网 发布:淘宝网上开店要钱吗 编辑:程序博客网 时间:2024/05/21 17:12
题目来源:POJ
题意:在墙上贴海报,后贴的会覆盖之前的,问最后能看见几张海报
线段树染色问题,注意题目里每个数字代表一个单位长度而不是点,普通离散化会出现问题。以下例子来自NotOnlySuccess菊苣的博客
“例子一: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是否被完全覆盖掉了呢?
例子一是完全被覆盖掉了,而例子二没有被覆盖”
针对这个问题,网上常见的做法是对离散化的数组做一个小处理。以下同样来自NotOnlySuccess菊苣的博客
”为了解决这种缺陷,我们可以在排序后的数组上加些处理,比如说[1,2,6,10]
如果相邻数字间距大于1的话,在其中加上任意一个数字,比如加成[1,2,3,6,7,10],然后再做线段树就好了.“
但是,这样做会增加maxn的大小……令人难以忍受……
事实上,只要在输入[l, r]的时候进行处理,变成[l, r + 1],相当于线段树存储的是一整段区间的信息(传说中的“段树”),就可以应用普通离散化了,具体见代码
另外,由于POJ这题数据奇弱无比,一种叫做浮水法的n^2的做法也是可以过的,这个是我搜本题题解的时候搜到的一种做法,网上资料很少,下面同样附上代码和本人的理解o( ̄▽ ̄)ブ
浮水法:本题中,将每条线段和其后的线段进行比较,没有重叠部分就继续和下一条比较,有重叠部分则去掉重叠部分再继续比较,比较是递归的。这个递归过程就像一层一层上浮最后浮到水面上一样,所以叫浮水法(联想到冒泡)。如果某条线段最后能浮到水面上,ans++
// 线段树#include <algorithm>#include <cctype>#include <cmath>#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <map>#include <queue>#include <string>#define ALL(v) v.begin(), v.end()#define CLR(array) memset(array, 0, sizeof(array))#define DEBUG cout << "bug "#define Fr first#define FOR(i, n) for(int i = 0; i < n; i++)#define MEM(array) memset(array, 0x3f, sizeof(array))#define ls L(id)#define lson id << 1, l, mid#define OFF(array) memset(array, -1, sizeof(array))#define PR(x) cout << #x << " = " << x << " "#define PRLN(x) cout << #x << " = " << x << endl#define rep(i, a, b) for(int i = a; i <= b; i++)#define root 1, 1, n#define rs R(id)#define rson id << 1 | 1, mid, r // 注意这里是 mid#define Rep(i, a, b) for(int i = a; i >= b; i--)#define repk(i, a, b) for(i = a; i <= b; i++)#define Repk(i, a, b) for(i = a; i >= b; i--)#define Sc second#define SZ size()using namespace std;inline int L(int x){ return x << 1; }inline int R(int x){ return x << 1 | 1; }inline int MID(int l, int r){ return l + r >> 1; }typedef long long ll;typedef pair<int, int> P;const int inf = 0x3f3f3f3f, maxn = 2e4 + 5;int color[maxn << 2];int x[maxn >> 1], y[maxn >> 1];int vis[maxn >> 1];void push_down(int id) { color[ls] = color[rs] = color[id]; color[id]= -1;}void update(int id, int l, int r, int a, int b, int val) { if(a <= l && r <= b) { color[id] = val; return; } if(r > l && ~color[id]) push_down(id); int mid = MID(l, r); if(mid > a) update(lson, a, b, val); //第一次写段树,一开始总是莫名崩溃,后来发现此处的判断跟点树不一样,不应该有等号,否则会无限递归 -> 越界 if(mid < b) update(rson, a, b, val);}void query(int id, int l ,int r) { if(~color[id]) { vis[color[id]] = 1; return; } if(l + 1 == r) return; int mid = MID(l, r); query(lson); query(rson);}int compress(int m) { // 离散化部分 vector<int> v; FOR(i, m) { scanf("%d%d", x + i, y + i); y[i]++; // 此处 +1, 使 x[i], y[i] 表示区间的左右端点 v.push_back(x[i]); v.push_back(y[i]); } sort(ALL(v)); v.resize(unique(ALL(v)) - v.begin()); FOR(i, m) { x[i] = 1 + lower_bound(ALL(v), x[i]) - v.begin(); y[i] = 1 + lower_bound(ALL(v), y[i]) - v.begin(); } return v.SZ;}int solve(void) { int n, m, ans = 0; scanf("%d", &m); n = compress(m); color[1] == m; //开始全部无色,用 m 表示 FOR(i, m) update(root, x[i], y[i], i); CLR(vis); query(root); FOR(i, m) if(vis[i]) ans++; return ans;}int main(void) { freopen("F:\\Desktop\\in.txt", "r", stdin); int t; scanf("%d", &t); while(t--) printf("%d\n", solve()); return 0;}
// 浮水法// 此处省略头文件50行const int inf = 0x3f3f3f3f, maxn = 1e4 + 5;int a[maxn], b[maxn];int n;int cover(int l, int r, int id) { if(id > n) return 1; int nowl = a[id], nowr = b[id]; if(l > nowr || r < nowl) return cover(l, r, id + 1); if(r > nowr && cover(nowr + 1, r, id + 1)) return 1; if(nowl > l && cover(l, nowl - 1, id + 1)) return 1; return 0;}int solve(void) { int ans = 0; scanf("%d", &n); rep(i, 1, n) scanf("%d%d", a + i, b + i); rep(i, 1, n) if(cover(a[i], b[i], i + 1)) ans++; return ans;}int main(void) { freopen("F:\\Desktop\\in.txt", "r", stdin); int t; scanf("%d", &t); while(t--) printf("%d\n", solve()); return 0;}
- (重温)poj 2528 Mayor's posters 线段树 染色+离散化
- poj 2528 Mayor's posters(线段树+离散化,染色)
- POJ 2528 Mayor's posters(线段树染色+离散化)
- POJ 2528 Mayor's posters (区间离散化、线段树区间染色)
- POJ 2528 Mayor's posters (线段树+离散化)
- POJ 2528 Mayor's posters (线段树+离散化)
- poj 2528 Mayor's posters(离散化+线段树)
- POJ 2528 Mayor's posters(线段树+离散化)
- POJ - 2528 Mayor's posters (线段树+离散化)
- poj 2528 Mayor's posters(线段树,离散化)
- POJ 2528 Mayor's posters(线段树+离散化)
- POJ 2528 Mayor's posters(线段树+离散化)
- POJ 2528 Mayor's posters(线段树+离散化)
- POJ 2528 Mayor's posters(离散化线段树)
- POJ 2528 Mayor's posters(离散化 + 线段树)
- POJ 2528 Mayor's posters(线段树+离散化)
- POJ 2528 Mayor's posters(线段树+离散化)
- POJ 2528 Mayor's posters (离散化 + 线段树)
- MyBatis第三种方式,xml和接口的结合,以及如何获得插入数据的返回参数、传入空的参数
- 1055 -- 矩阵乘法
- UITextView根据键盘自适应边框
- Qt在Windows下的三种编程环境搭建
- 1056 -- 三点顺序
- POJ 2528 Mayor's posters(线段树染色+离散化)
- Inside Qt Series (十四):Qt/e输入法程序设计指南
- 浅谈L0,L1,L2范数及其应用
- 1057 -- 评委打分
- ex14
- 高效率地安排见面会
- 1042. Shuffling Machine (20)
- 1058 -- 货币兑换
- 支付宝扫描支付——app端无法显示二维码等问题的解决方式