POJ 3277 线段树 + 延迟标记
来源:互联网 发布:淘宝黑莓手机是真的吗 编辑:程序博客网 时间:2024/05/29 14:01
本题就是给出一堆矩形,然后让我们算总共的面积,也就是重复的面积只算一次。需要用到线段树,每次输入矩形的左端点和右端点,还有高。我们就把这条线段插进去,线段的高度取较高的那一个。注意到这和普通的线段树不太一样,普通的情况是,当我们插入的线段完全覆盖线段树中的某一条线段时,那条线段的值就被更新成插入的线段的值。但是本题的情况却不太一样,当我们插入的线段完全覆盖线段树的某一条线段时,如果现在的权值大于原有线段的权值,就将其覆盖。但是一定要注意,更新之后的线段树的值并不一定是正确的。
比如我们最先插入(1,5),5。然后打上延迟标记。第二次插入(1,3),7。所以我们就把延迟标记下移。(1,3)和(3,5)都更新成5,然后(1,3)变成7。然后再把(1,5)更新成6。现在假如我们来查询,难道(1,5)的值就是6吗?明显不是,(1,3)区间的权值是7,(3,5)区间的值为5。那么怎么才能查询到正确的结果呢?只需要从根节点,不断的往叶子节点更新就行了。
所以这道题:
1.更新的时候延迟标记下移的规则不是完全覆盖,是取一个区间中的最大值
2.查询的时候,从根节点往叶子节点更新
3.本题线段树叶子节点应该构建成(x,x + 1)的形式,不然会漏掉[m,m + 1]的面积
#include <algorithm>#include <iostream>#include <iterator>#include <sstream>#include <fstream>#include <istream>#include <ostream>#include <complex>#include <cstring>#include <utility>#include <cstdlib>#include <cstdio>#include <vector>#include <string>#include <cctype>#include <ctime>#include <cmath>#include <queue>#include <stack>#include <list>#include <new>#include <set>#include <map>#define lson l, m, k << 1#define rson m, r, k << 1| 1using namespace std;typedef long long int LL;const int INF = 0x3f3f3f3f;const int maxn = 200000 << 2;LL cover[maxn], maxh[maxn], li[maxn], ri[maxn], hi[maxn], x[maxn];void pushdown(int k){ if (cover[k]){ if (maxh[k << 1] < maxh[k]){ maxh[k << 1] = maxh[k]; cover[k << 1] = 1; } if (maxh[k << 1 | 1] < maxh[k]){ maxh[k << 1 | 1] = maxh[k]; cover[k << 1 | 1] = 1; } cover[k] = 0; }}void update(int l, int r, int k, int L, int R, int H){ if (L == l && R == r){ if (maxh[k] < H){ maxh[k] = H; cover[k] = 1; } return; } pushdown(k); int m = (l + r) >> 1; if (R <= m) update(lson, L, R, H); else if (L >= m) update(rson, L, R, H); else{ update(lson, L, m, H); update(rson, m, R, H); }}LL query(int l, int r, int k){ if (l == r - 1) return maxh[k] * (x[r] - x[l]); maxh[k << 1] = max(maxh[k], maxh[k << 1]); maxh[k << 1 | 1] = max(maxh[k], maxh[k << 1 | 1]); int m = (l + r) >> 1; return query(lson) + query(rson);}int Binary_Search(int s, int e, int key) { int left = s, right = e, mid; while (left <= right) { mid = (left + right) >> 1; if (x[mid] >= key) right = mid - 1; else left = mid + 1; } if (x[left] == key) return left; return -1;}int main(){ //freopen("1.txt", "r", stdin); int n; scanf ("%d", &n); int nn = 0; for (LL i = 1; i <= n; i++) { scanf ("%I64d%I64d%I64d", &li[i], &ri[i], &hi[i]); x[++nn] = li[i]; x[++nn] = ri[i]; } memset(maxh, 0, sizeof(maxh));//建树 memset(cover, 0, sizeof(cover)); sort(x + 1, x + nn + 1);//离散化 int len = unique(x + 1, x + nn + 1) - (x + 1); for (LL i = 1; i <= n; i++) { LL l = Binary_Search(1, len + 1, li[i]); LL r = Binary_Search(1, len + 1, ri[i]); update(1, len, 1, l, r, hi[i]); } printf("%I64d\n", query(1, len, 1)); return 0;}
0 0
- POJ 3277 线段树 + 延迟标记
- poj 3468 线段树,延迟标记法
- poj 3468 线段树延迟标记
- 线段树 延迟标记
- 线段树模板 (poj 3468)延迟标记
- POJ 3667 线段树 + 延迟标记 + 区间处理
- POJ 3667 Hotel(线段树+区间合并+延迟标记)
- POJ 2528 线段树 + 延迟标记 + 离散化
- POJ 2528 线段树(离散化+延迟标记)
- HDU1698(线段树+延迟标记)
- 浅析__线段树延迟标记
- lightoj1135(线段树 + 延迟标记)
- 线段树延迟标记精讲
- 线段树区间更新延迟标记
- 线段树延迟标记精讲
- POJ3468 线段树 + Lazy Tag (延迟标记)
- hdu3911(线段树,区间合并,延迟标记)
- 线段树(类似延迟标记) HDU
- JVM:编译加载机制与自定义类加载器
- 前端50本书籍下载
- 怎么记住1月-12月的英文
- Redhat6.x bond配置
- Receiver not registered: android.widget.ZoomButtonsController crash android
- POJ 3277 线段树 + 延迟标记
- Android MediaPlayer和VideoView的使用
- ios7之后导航栏的问题1
- jdbcTemplate的简单使用
- Lightoj 1067【逆元模板(求C(N,M))】
- Android Image开源框架之ImageLoader(二)
- Virtual关键字
- C/C++的64位整型 不同编译器间的比较
- 对URL URI URN的思考