HDU - 5156 Harry and Christmas tree
题目链接 : http://acm.hdu.edu.cn/showproblem.php?pid=5156
题意 :
给一颗编号为1-n的以1为根的树, 已知有m个颜色的礼物分布在某些节点上(同一节点可以有多个),
问 : 对于编号从1-n的节点, 每一个节点对应子树上有多少颜色不同的礼物.
思路 :
一开始的想法是DFS记录节点序列, 再开vector记录每个节点上挂的礼物(同一节点上对颜色去重), 用树状数组统计一个区间内不同颜色的种类
但是由于记录位置的数组同样要开到二维, 超过了限制, 于是也开成vector, 果断超时
后来还是看discuss里边sxbk同学的代码才知道更好的解法
DFS记录序列不是节点序列, 而是将所有节点的全部颜色(已去重)都记录在序列内, 这样位置记录的数组可以只用一维
这道题收获挺大的, 对DFS序的思想理解深入了, 同时学习了 统计一个区间内有多少不同的数 这个问题的解法
题目代码 :
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector> using namespace std; const int MAXN = 5e4+;
const int MAXM = 5e5+; vector<int> edge[MAXN];
vector<int> gift[MAXN];
int seq[*MAXM];
int st[MAXN];
int ed[MAXN];
int s[*MAXM];
int mp[*MAXM];
int ans[MAXN];
int pos[MAXN];
int cnt, n, m; void Dfs(int u, int fa)
{
st[u] = cnt + ;
int num = gift[u].size();
for(int i = ; i < num; i++) {
seq[++cnt] = gift[u][i];
}
int len = edge[u].size();
for(int i = ; i < len; i++) {
int v = edge[u][i];
if(v != fa) Dfs(v, u);
}
ed[u] = cnt;
} int Lowbit(int x)
{
return x & (-x);
} void Add(int x, int val)
{
for(int i = x; i <= cnt; i += Lowbit(i)) {
s[i] += val;
}
} int Sum(int x)
{
int res = ;
for(int i = x; i > ; i -= Lowbit(i)) {
res += s[i];
}
return res;
} bool cmp(int a, int b)
{
return ed[a] < ed[b];
} void Init()
{
for(int i = ; i <= n; i++) {
edge[i].clear();
gift[i].clear();
}
for(int i = ; i <= n; i++) {
pos[i] = i;
}
memset(s, , sizeof(s));
memset(mp, , sizeof(mp));
} int main()
{
int u, v; while(scanf("%d %d", &n, &m) != EOF) {
Init();
for(int i = ; i < n-; i++) {
scanf("%d %d", &u, &v);
edge[u].push_back(v);
edge[v].push_back(u);
}
while(m--) {
scanf("%d %d", &u, &v);
if(find(gift[u].begin(), gift[u].end(), v) == gift[u].end()) {
gift[u].push_back(v);
}
}
cnt = ;
Dfs(, -);
sort(pos+, pos++n, cmp);
for(int i = ; i <= cnt; i++) {
if(mp[seq[i]] == ) {
Add(i, );
mp[seq[i]] = i; //如果是第一次出现, mp[seq[i]]记录为当前位置
}
}
int right = ;
for(int i = ; i <= n; i++) {
int now = pos[i];
while(right <= ed[now]) {
if(mp[seq[right]] != right) { //如果不是第一次出现
Add(mp[seq[right]], -); //减去前一次出现的
Add(right, );
mp[seq[right]] = right; //重新定义这个数最近一次出现位置
}
right++;
}
ans[now] = Sum(ed[now]) - Sum(st[now] - );
}
printf("%d", ans[]);
for(int i = ; i <= n; i++) {
printf(" %d", ans[i]);
}
printf("\n");
} return ;
}
另外第一次学习到 统计一个区间内有多少不同的数 这个问题的解法
基本思路是树状数组, 但是有重复的数, 要保证在一个区间内只更新过一次
所做的处理是用先遍历记录数字的数组a, 用数-位置数组 mp[a[i]] 来记录每个数第一次出现的位置并该点更新
这个操作对应的代码
for(int i = ; i <= n; i++) {
if(mp[a[i]] == ) { //如果是第一次出现, 记录第一次出现位置并更新
Add(i, );
mp[a[i]] = i;
}
}
记录左右查询, 每个查询按区间右端点R[i]从小到大排序
设一个扫描线k, 它的目的保证R[i]之前所有不同的点只更新过一次, 并且是在离R[i]最近的那个点更新
如此便可以写出这样一段代码
for(int i = ; i <= query_num; i++) {
while(k <= R[i]) {
if(mp[a[i]] != k) { //如果不是最新次出现
Add(mp[a[k]], -); //将上一次出现的更新-1
Add(k, ); //将这个位置新出现的更新1
mp[a[k]] = k; //更新这个数最近一次的位置
}
k++;
}
ans[i] = Sum(ed[i]) - Sum(st[i] - );
}
恩, 就是这样...
HDU - 5156 Harry and Christmas tree的更多相关文章
- POJ3013 Big Christmas Tree[转换 最短路]
Big Christmas Tree Time Limit: 3000MS Memory Limit: 131072K Total Submissions: 23387 Accepted: 5 ...
- poj 3013 Big Christmas Tree (最短路径Dijsktra) -- 第一次用优先队列写Dijsktra
http://poj.org/problem?id=3013 Big Christmas Tree Time Limit: 3000MS Memory Limit: 131072K Total S ...
- poj 3013 Big Christmas Tree Djistra
Big Christmas Tree 题意:图中每个节点和边都有权值,图中找出一颗树,树根为1使得 Σ(树中的节点到树根的距离)*(以该节点为子树的所有节点的权值之和) 结果最小: 分析:直接求出每个 ...
- hdu 4912 Paths on the tree(树链拆分+贪婪)
题目链接:hdu 4912 Paths on the tree 题目大意:给定一棵树,和若干个通道.要求尽量选出多的通道,而且两两通道不想交. 解题思路:用树链剖分求LCA,然后依据通道两端节点的LC ...
- POJ 3013 Big Christmas Tree(最短Dijkstra+优先级队列优化,SPFA)
POJ 3013 Big Christmas Tree(最短路Dijkstra+优先队列优化,SPFA) ACM 题目地址:POJ 3013 题意: 圣诞树是由n个节点和e个边构成的,点编号1-n. ...
- POJ Big Christmas Tree(最短的基础)
Big Christmas Tree 题目分析: 叫你构造一颗圣诞树,使得 (sum of weights of all descendant nodes) × (unit price of the ...
- poj 3013 Big Christmas Tree
Big Christmas Tree Time Limit: 3000MS Memory Limit: 131072K Total Submissions: 20974 Accepted: 4 ...
- Big Christmas Tree(poj-3013)最短路
Big Christmas Tree Time Limit: 3000MS Memory Limit: 131072K Total Submissions: 25823 Accepted: 5 ...
- (hdu)5423 Rikka with Tree (dfs)
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5423 Problem Description As we know, Rikka is p ...
随机推荐
- java中说明书/开发文档如何编写?
由于在java开发时我们得到的或者给别人的文件一般都是class文件,不会给出源文件,故编写一个简洁易懂的说明书是必须的. ps: @param int[] arr 会有警告,可以删掉 int []. ...
- SQL 结构化查询语言手册
摘自该学习网站: http://www.w3school.com.cn/sql/ 新学到的几点: and 和or 连用,记得用括号. 2.SQL通配符补充 例如: ...
- 怎么在Linux上下载并安装ESET NOD32 Antivirus 4桌面版
转自:怎么在Linux上下载并安装ESET NOD32 Antivirus 4桌面版 下载并安装ESET NOD32 Antivirus 4的Linux桌面版,根据下面的步骤一步一步的来: I. 下 ...
- 异步tcp通信——APM.Core 解包
TCP通信解包 虽说这是一个老生长谈的问题,不过网上基本很少见完整业务:或多或少都没有写完或者存在bug.接收到的数据包可以简单分成:小包.大包.跨包三种情况,根据这三种情况作相对应的拆包处理,示例如 ...
- 渲染器 Shader BitmapShader
渲染模式: tileX tileY:The tiling mode for x/y to draw the bitmap in. 在位图上 X/Y 方向 瓦工/花砖/瓷砖 模式 CLAMP :如 ...
- WinHeap.H
网上找到的,对 Windows Heap 有详细的定义. // file winheap.h typedef void VOID; typedef unsigned __int8 UINT8; typ ...
- cassandra新增、更新、删除数据。
package client; import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java ...
- UITableView初始
近期在自学IOS,看了黑马提供的视频,讲的很好.在此做些笔记,以供以后查阅.注明了知识来源应该不算侵权吧. 一 UITableView 1,数据展示的条件 1⃣️ UITableView的所有数据都是 ...
- MapReduce UnitTest
通常情况下,我们需要用小数据集来单元测试我们写好的map函数和reduce函数.而一般我们可以使用Mockito框架来模拟OutputCollector对象(Hadoop版本号小于0.20.0)和Co ...
- Debian、Ubuntu常用命令大全
注:本人是用的Debian,个别命令可能有问题. 原文:http://www.jb51.net/os/Ubuntu/56362.html 一.文件/文件夹管理 ls 列出当前目录文件(不包括隐含文件) ...