【题意】
有一面墙,被等分为1QW份,一份的宽度为一个单位宽度。现在往墙上贴N张海报,每张海报的宽度是任意的,但是必定是单位宽度的整数倍,且<=1QW。后贴的海报若与先贴的海报有交集,后贴的海报必定会全部或局部覆盖先贴的海报。现在给出每张海报所贴的位置(左端位置和右端位置),问张贴完N张海报后,还能看见多少张海报?(PS:看见一部分也算看到。)
/* translation: 有一堵墙,往上面贴海报,每张海报有各自的范围,可以相互覆盖,求最后还能看见多少张海报? solution: 线段树,离散化 每张海报的粘贴就是一个区间操作,所以可以考虑用线段树来解决。但是题目中所给的墙的长度数据量太大,都存下来 肯定MLE,所以考虑利用离散化,将每张海报的端点存储下来。然后利用这些端点来建立一颗线段树。然后就是查询操作 了,为了不让先后顺序相互影响,所以将逆序粘贴海报。这样每个节点中的covered信息就不会收到后来海报的影响。 note: date: 2016.11.18 */
#include <iostream> #include <cstdio> #include <algorithm> using namespace std; const int maxn = 20000 + 5; int pl[maxn], pr[maxn], n; //海报 int s[maxn*4], e[maxn*4]; bool covered[maxn*4]; //线段树节点保存信息 int port[maxn], cnt; //保存离散后的端点 int id[10000000+5]; //保存离散后各个端点所在的位置编号 void build_tree(int l, int r, int rt) { s[rt] = l; e[rt] = r; covered[rt] = false; if(l != r){ build_tree(l, (l + r) / 2, rt << 1); build_tree((l + r) / 2 + 1, r, rt << 1 | 1); } } bool post(int l, int r, int rt) { if(covered[rt] == true) return false; if(s[rt] == l && e[rt] == r){ covered[rt] = true; return true; } bool res; if(r <= (s[rt] + e[rt]) / 2) res = post(l, r, rt << 1); else if(l > (s[rt] + e[rt]) / 2) res = post(l, r, rt << 1 | 1); else { bool res1 = post(l, (s[rt] + e[rt]) / 2, rt << 1); bool res2 = post((s[rt] + e[rt]) / 2 + 1, r, rt << 1 | 1); res = res1 || res2; } if(covered[rt << 1] && covered[rt << 1 | 1]) covered[rt] = true; return res; } int main() { //freopen("in.txt", "r", stdin); //freopen("out1.txt", "w", stdout); int T; scanf("%d", &T); while(T--){ scanf("%d", &n); cnt = 0; for(int i = 0; i < n; i++){ scanf("%d%d", &pl[i], &pr[i]); port[cnt++] = pl[i]; port[cnt++] = pr[i]; } sort(port, port + cnt); cnt = unique(port, port + cnt) - port; //离散化 build_tree(1, cnt, 1); //建立线段树 for(int i = 0; i < cnt; i++) id[port[i]] = i + 1; int res = 0; for(int i = n-1; i >= 0; i--){ if(post(id[pl[i]], id[pr[i]], 1)){ res++; //printf("pl:%d pr:%d ", pl[i], pr[i]); } } printf("%d ", res); } return 0; } ———————————————— 版权声明:本文为CSDN博主「林伏案」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/qq_29169749/article/details/53223002
【改编】电线杆上的小广告
#include <bits/stdc++.h> const int N = 1e5 + 9; struct Data { int num; int lorr; // 0:left 1:right int id; bool operator<(Data b) { return num < b.num; } } d[N << 1]; int n, m, H, lr[N][2]; bool e[N]; int c[N << 3], tg[N << 3]; void pushdown(int o) { if (tg[o]) { c[o << 1] = c[o << 1 | 1] = tg[o]; tg[o << 1] = tg[o << 1 | 1] = tg[o]; } tg[o] = 0; } void modi(int o, int lo, int ro, int lm, int rm, int cm) { if (lo != ro) pushdown(o); if (lm <= lo && ro <= rm) { c[o] = tg[o] = cm; return; } int mo = lo + ro >> 1; if (lm <= mo) modi(o << 1, lo, mo, lm, rm, cm); if (mo < rm) modi(o << 1 | 1, mo + 1, ro, lm, rm, cm); } int query(int o, int lo, int ro, int v) { if (v == lo && v == ro) return c[o]; pushdown(o); int mo = lo + ro >> 1; if (v <= mo) return query(o << 1, lo, mo, v); else return query(o << 1 | 1, mo + 1, ro, v); } int main() { scanf("%d%d", &n, &H); for (int i = 0; i < n; ++i) { int h, a; scanf("%d%d", &h, &a); d[i << 1] = Data{ h, 0, i }; d[i << 1 | 1] = Data{ h + a, 1, i }; } std::sort(d, d + n + n); lr[d[0].id][d[0].lorr] = m = 1; for (int i = 1; i < n + n; ++i) lr[d[i].id][d[i].lorr] = (m += (d[i].num != d[i - 1].num)); for (int i = 0; i < n; ++i) { modi(1, 1, m, lr[i][0], lr[i][1], i + 1); } for (int i = 1; i <= m; ++i) { int x = query(1, 1, m, i); e[x] = true; } for (int i = 1; i <= n; ++i) if (!e[i]) printf("%d ", i - 1); }