HDU 5200 Tree (离线并查集)
2015-09-19 20:47
225 查看
Trees
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1146 Accepted Submission(s): 363
Problem Description
Today CodeFamer is going to cut trees.There areN
trees standing in a line. They are numbered from 1
to N.
The tree numbered i
has height hi.
We say that two uncutted trees whose numbers are x
and y
are in the same block if and only if they are fitting in one of blow rules:
1)x+1=y or y+1=x;
2)there exists an uncutted tree which is numbered z,
and x
is in the same block with z,
while y
is also in the same block with z.
Now CodeFamer want to cut some trees whose height is not larger than some value, after those trees are cut, how many tree blocks are there?
Input
Multi test cases (about
15).
For each case, first line contains two integers N
and Q
separated by exactly one space, N indicates there are
N
trees, Q
indicates there are Q
queries.
In the following N
lines, there will appear h[1],h[2],h[3],…,h[N]
which indicates the height of the trees.
In the following Q
lines, there will appear q[1],q[2],q[3],…,q[Q]
which indicates CodeFamer’s queries.
Please process to the end of file.
[Technical Specification]
1≤N,Q≤50000
0≤h[i]≤1000000000(109)
0≤q[i]≤1000000000(109)
Output
For each
q[i],
output the number of tree block after CodeFamer cut the trees whose height are not larger thanq[i].
Sample Input
3 2 5 2 3 6 2
Sample Output
0 2 HintIn this test case, there are 3 trees whose heights are 5 2 3. For the query 6, if CodeFamer cuts the tree whose height is not large than 6, the height form of left trees are -1 -1 -1(-1 means this tree was cut). Thus there is 0 block. For the query 2, if CodeFamer cuts the tree whose height is not large than 2, the height form of left trees are 5 -1 3(-1 means this tree was cut). Thus there are 2 blocks.
Source
BestCoder Round #36 ($)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5200
题目大意:有n棵树,每棵高度位hi,q个询问,每次砍掉高度不大于qi的树,每个询问后输出当前有树的区域被分成了几块
题目分析:典型的离线并查集,把没被砍掉的树并到一起,查询的高度从大到小排序,因为如果qi > qj的话,qi时被合并的树在qj时显然还是并在一起的,注意这里还需要对树高从大到小排序,这是一个防止超时的优化,即如果当前的树高度比qi小了,那就可以退出了,因为后面的树肯定都要被砍掉,每枚举一棵树cnt就要加1,每合并一次,cnt要减1,最后用id记录询问编号
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; int const MAX = 1e5 + 5; int ans[MAX], fa[MAX], h[MAX]; int n, Q, cnt; struct DATA { int id, h; }q[MAX], s[MAX]; bool cmp(DATA a, DATA b) { return a.h > b.h; } void UF_set() { for(int i = 0; i <= n; i++) fa[i] = i; } int Find(int x) { return x == fa[x] ? x : fa[x] = Find(fa[x]); } void Union(int a, int b) { int r1 = Find(a); int r2 = Find(b); if(r1 != r2) { fa[r1] = r2; cnt --; } } int main() { while(scanf("%d %d", &n, &Q) != EOF) { cnt = 0; UF_set(); for(int i = 1; i <= n; i++) { scanf("%d", &h[i]); s[i].h = h[i]; s[i].id = i; } h[0] = h[n + 1] = 0; for(int i = 1; i <= Q; i++) { scanf("%d", &q[i].h); q[i].id = i; } sort(s + 1, s + n + 1, cmp); sort(q + 1, q + Q + 1, cmp); int j = 1; for(int i = 1; i <= Q; i++) { while(j <= n && h[s[j].id] > q[i].h) { cnt ++; if(h[s[j].id - 1] > q[i].h) Union(s[j].id - 1, s[j].id); if(h[s[j].id + 1] > q[i].h) Union(s[j].id + 1, s[j].id); j ++; } ans[q[i].id] = cnt; } for(int i = 1; i <= Q; i++) printf("%d\n", ans[i]); } }
相关文章推荐
- HTML(网页设计)基础到加强
- 我所欣赏的一些学习习惯
- 数据结构之链表
- hdu 5452 Minimum Cut 求最小割边集的大小
- 使用C# 与Xero OAuth 交互 集成
- GBK 字节数分割字符数
- 用SQL Server实现建表和实现增删改
- 阐述linux IPC(两):基于socket进程间通信(下一个)
- SVN与eclipse整合和利用、SVN与Apache综合
- C# 设置MDI子窗体只能弹出一个的方法
- Python 脚本学习笔记(四) 定制业务质量报表
- Python 脚本学习笔记(四) 定制业务质量报表
- Python 脚本学习笔记(四) 定制业务质量报表
- 定制Enhancedgrid的description内容
- Effective C++——条款46(第7章)
- JAVA科学计数法转普通计数法
- C# 启动外部程序的几种常用方法汇总
- Java基础知识强化45:StringBuffer类之字符串反转的案例
- RPM
- Android聊天机器人