ACM/ICPC 之 数据结构-线段树+区间离散化(POJ2528)
这道题用线段树做更方便更新和查询,但是其数据范围很大,因此要将离散化和线段树结合起来,算是一道比较经典的线段树+离散化的例题。
线段树的离散化有很多方法,在这里,我先用一次结点离散化,间接将源左右端点离散化的想法实现。(受到一个博客的启发)
题意:贴海报-给出海报左右端点,然后顺序贴上,问最后有多少海报可见。
直接贴上Code,具体解释在注释中有提及(有不懂的地方可以在纸上打个线段树草稿试试):
//贴海报-给出海报左右端点,顺序贴上,问最后有多少海报可见。
//Time:79Ms Memory:2712K
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std; #define MAX 10005 struct Node {
int l, r, kind;
}tr[16*MAX]; //两端点加空点需要8-16*MAX数据量 struct Pos {
int num, id;
friend bool operator < (Pos p1, Pos p2) { return p1.num < p2.num; }
}pos[2*MAX]; int n, cnt;
int l[MAX], r[MAX];
bool v[MAX]; void build(int x,int l,int r)
{
tr[x].l = l; tr[x].r = r;
if (l == r) return;
int mid = (l + r) / 2;
build(2 * x, l, mid);
build(2 * x + 1, mid + 1, r);
} void update(int x,int l,int r,int k)
{
if (tr[x].l == l && tr[x].r == r) {
tr[x].kind = k;
return;
}
if (tr[x].kind) {
tr[2 * x].kind = tr[x].kind;
tr[2 * x + 1].kind = tr[x].kind;
tr[x].kind = 0;
}
int mid = (tr[x].l + tr[x].r) / 2;
if (r <= mid) update(2 * x, l, r, k);
else if (l > mid) update(2 * x + 1, l, r, k);
else {
update(2 * x, l, mid, k);
update(2 * x + 1, mid + 1, r, k);
}
} int query(int x,int l,int r)
{
if (tr[x].kind) {
if (v[tr[x].kind]) return 0;
else { v[tr[x].kind] = true; return 1;}
}
if (tr[x].l == tr[x].r) return 0; //由于有空点,可能会有tr[x].kind = 0
int mid = (tr[x].l + tr[x].r) / 2;
return query(2 * x, l, mid) + query(2 * x + 1, mid + 1, r);
} int main()
{
int T;
scanf("%d", &T);
while (T--) {
memset(tr, 0, sizeof(tr));
memset(v, 0, sizeof(v));
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
scanf("%d%d", &l[i], &r[i]);
pos[2 * i].num = l[i];
pos[2 * i + 1].num = r[i];
pos[2 * i].id = 2 * i; //偶数-左端点
pos[2 * i + 1].id = 2 * i + 1; //奇数-右端点
}
int last = pos[0].num;
cnt = 1;
sort(pos, pos + 2 * n);
for (int i = 0; i < 2 * n; i++)
{
if (last != pos[i].num) {
if (pos[i].num - last > 1)
cnt++; //不相邻时,中间空一点
cnt++;
last = pos[i].num;
}
int id = pos[i].id; //分别对左右端点离散化
id % 2 ? r[id/2] = cnt : l[id/2] = cnt;
}
build(1, 1, cnt);
for (int i = 0; i < n; i++)
update(1, l[i], r[i], i + 1);
printf("%d\n", query(1, 1, cnt));
} return 0;
}
ACM/ICPC 之 数据结构-线段树+区间离散化(POJ2528)的更多相关文章
- ACM/ICPC 之 数据结构-线段树思想(POJ2182,含O(n^2)插入式解法)
这道题在一定程度上体现了线段树的一种用法,解决的问题是:对于总计n个元素的第i个元素,已知其在[1,i]上部分序列的排名,求第i个元素在所有n个元素中的排名. 当然这道题数据比较水,所以用O(n^2) ...
- 线段树区间离散化维护按秩合并并查集(可撤销)——牛客多校第八场E
模板题..去网上学了可撤销的并查集.. /* 给定一个无向图,边的属性为(u,v,l,r),表示<u,v>可以通过的size为[l,r] 求出有多少不同的size可以从1->n 把每 ...
- ACM: Hotel 解题报告 - 线段树-区间合并
Hotel Time Limit:3000MS Memory Limit:65536KB 64bit IO Format:%lld & %llu Description The ...
- 线段树区间离散化——牛客多校E
这个区间离散化把我调死了.. 总之用vector来离散化,然后叶子节点维护的是一段区间,记录下每个叶子结点的起点+长度 千万要注意下标不能弄错! #include<bits/stdc++.h&g ...
- hiho1116 - 数据结构 线段树(区间合并)
题目链接 现在有一个有n个元素的数组a1, a2, ..., an. 记f(i, j) = ai * ai+1 * ... * aj. 初始时,a1 = a2 = ... = an = 0,每次我会修 ...
- 计蒜客 38229.Distance on the tree-1.树链剖分(边权)+可持久化线段树(区间小于等于k的数的个数)+离散化+离线处理 or 2.树上第k大(主席树)+二分+离散化+在线查询 (The Preliminary Contest for ICPC China Nanchang National Invitational 南昌邀请赛网络赛)
Distance on the tree DSM(Data Structure Master) once learned about tree when he was preparing for NO ...
- POJ-2528 Mayor's posters (线段树区间更新+离散化)
题目分析:线段树区间更新+离散化 代码如下: # include<iostream> # include<cstdio> # include<queue> # in ...
- POJ 2528 Mayor's posters (线段树区间更新+离散化)
题目链接:http://poj.org/problem?id=2528 给你n块木板,每块木板有起始和终点,按顺序放置,问最终能看到几块木板. 很明显的线段树区间更新问题,每次放置木板就更新区间里的值 ...
- POJ.2528 Mayor's posters (线段树 区间更新 区间查询 离散化)
POJ.2528 Mayor's posters (线段树 区间更新 区间查询 离散化) 题意分析 贴海报,新的海报能覆盖在旧的海报上面,最后贴完了,求问能看见几张海报. 最多有10000张海报,海报 ...
随机推荐
- vim 配置,我本机的配置[windows]
set nocompatible source $VIMRUNTIME/vimrc_example.vim source $VIMRUNTIME/mswin.vim behave mswin set ...
- 第二章平稳时间序列模型——ACF和PACF和样本ACF/PACF
自相关函数/自相关曲线ACF AR(1)模型的ACF: 模型为: 当其满足平稳的必要条件|a1|<1时(所以说,自相关系数是在平稳条件下求得的): y(t)和y(t-s)的 ...
- 1、Java背景、标示符、运算符、转义字符
一.Java平台: 1.Java的创建:1991年由SUN公司创建. 2.Java的特点:面向对象.可移植性.多线程.分布式.可靠.安全. 3.Java的三个架构:JavaEE.JavaSElect. ...
- HDOJ 4389 X mod f(x)
数位DP........ X mod f(x) Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/ ...
- Ubuntu 14 如何创建软件的 启动器/桌面图标?
如题所示:Ubuntu 14 如何创建软件的 启动器/桌面图标? 解决方案: 将 /usr/share/applications/ 里面的相应图标复制到桌面即可. 同理,也可“拖动”到左边的“启动器栏 ...
- Junit基础整理
项目引进Junit包 对待测试类新建testcase testcase类分为:@RunWith() -----@RunWith(suite.class)测试套件类打包测试 -----@RunWith( ...
- 计算字符数组长度,用strlen 与 sizeof 的原理与区别
遇到个坑,定义了一个字符数组 unsigned ;i<;i++) { buff[i] = ; } 然后用串口发送函数: write(fd, buff, strlen(buff)); 却发现串口一 ...
- mongodb python image 图像存储读取
最近做一些数据库调研的工作,目标是实现影像更快的入库.出库.查询,并实现并行访问等操作. 将结果总结成一个mongoImg类,也算是小结吧. ''' Created on 2013-8-6 class ...
- 如何把其他用户创建的表,导入到自己数据库是,所有者owner改变为自己创建的用户
1. 导出用户 expdp user1/pass1 directory=dumpdir dumpfile=user1.dmp2. 导入用户 impdp user2/pass2 directory=d ...
- HDU 5033 Building
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5033 解题报告:在一条x轴上有n个建筑物,每个建筑物有一个高度h,然后现在有q次查询,查询的内容是假设 ...