题意:给一棵树,每次给两个节点间的所有节点发放第k种东西,问最后每个节点拿到的最多的东西是哪种。

解法:解决树的路径上的修改查询问题一般用到的是树链剖分+线段树,以前不会写,后来学了一下树链剖分,感觉也不是很难,就是把整个数分成很多链,然后一条重链上的点在线段树中位置是连续的,这样使得更新和查询时更加便利。

这个题目中线段树应该维护的是种类,每次对u-v发放k时,可以让u处+k,v+1处-k,把这些都离线存起来,然后枚举1~n,分别把自己该做的操作都做了,然后统计的时候tree[1].type就是该点的type。

这题是借鉴别人的代码写的,总算对树链剖分的题有所了解了。

还有在HDU交C++会爆栈,要加一个扩栈语句,不想加交G++也可以。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std;
#define N 100007 int siz[N]; //子树大小
int son[N]; //重儿子
int dep[N]; //深度
int pos[N]; //在线段树中的位置
int apos[N]; //线段树中位置对应的点
int Top[N]; //所在重链的祖先
int fa[N]; //父节点
int ans[N]; //答案
int head[*N],tot,POS,n,m;
struct Edge
{
int v,next;
}G[*N]; struct Tree
{
int num,type;
}tree[*N]; struct node
{
int u,v,z;
node(){}
node(int _u,int _v,int _z):u(_u),v(_v),z(_z){}
};
vector<node> com;
vector<int> Q[N]; void init()
{
POS = tot = ;
memset(head,-,sizeof(head));
memset(son,-,sizeof(son));
com.clear();
for(int i=;i<=n+;i++)
Q[i].clear();
} void addedge(int u,int v)
{
G[tot].v = v, G[tot].next = head[u], head[u] = tot++;
G[tot].v = u, G[tot].next = head[v], head[v] = tot++;
} void pushup(int rt)
{
if(tree[*rt].num >= tree[*rt+].num)
tree[rt].type = tree[*rt].type;
else
tree[rt].type = tree[*rt+].type;
tree[rt].num = max(tree[*rt].num,tree[*rt+].num);
} void build(int l,int r,int rt)
{
tree[rt].num = ;
if(l == r)
{
tree[rt].type = l;
return;
}
int mid = (l+r)/;
build(l,mid,*rt);
build(mid+,r,*rt+);
pushup(rt);
} void update(int l,int r,int pos,int val,int rt)
{
if(l == r)
{
tree[rt].num += val;
return;
}
int mid = (l+r)/;
if(pos <= mid)
update(l,mid,pos,val,*rt);
else
update(mid+,r,pos,val,*rt+);
pushup(rt);
} void dfs(int u,int f)
{
dep[u] = dep[f]+;
siz[u] = ;
for(int i=head[u];i!=-;i=G[i].next)
{
int v = G[i].v;
if(v == f) continue;
fa[v] = u;
dfs(v,u);
if(son[u] == - || siz[v] > siz[son[u]]) son[u] = v;
siz[u] += siz[v];
}
} void dfs2(int u,int father)
{
pos[u] = ++POS;
apos[POS] = u;
Top[u] = father;
if(son[u] != -) dfs2(son[u],father); //有重儿子优先dfs
for(int i=head[u];i!=-;i=G[i].next)
{
int v = G[i].v;
if(v != fa[u] && v != son[u])
dfs2(v,v);
}
} void getcom(int u,int v,int z)
{
int fx = Top[u], fy = Top[v];
while(fx != fy)
{
if(dep[fx] < dep[fy])
{
swap(u,v);
swap(fx,fy);
}
com.push_back(node(pos[fx],pos[u],z));
u = fa[fx];
fx = Top[u];
}
if(dep[u] > dep[v]) swap(u,v);
com.push_back(node(pos[u],pos[v],z));
} int main()
{
int i,j,maxi,u,v,z;
while(scanf("%d%d",&n,&m)!=EOF && n+m)
{
init();
for(i=;i<n;i++)
{
scanf("%d%d",&u,&v);
addedge(u,v);
}
dep[] = ;
dfs(,);
dfs2(,);
maxi = ;
while(m--)
{
scanf("%d%d%d",&u,&v,&z);
getcom(u,v,z);
maxi = max(maxi,z);
}
int SIZE = com.size();
for(i=;i<SIZE;i++)
{
int u = com[i].u, v = com[i].v, z = com[i].z;
Q[u].push_back(z);
Q[v+].push_back(-z);
}
build(,maxi,);
for(i=;i<=n;i++)
{
sort(Q[i].begin(),Q[i].end());
int sz = Q[i].size();
for( j=;j<sz;j++)
{
int p = Q[i][j];
if(p < ) update(,maxi,-p,-,);
else update(,maxi,p,,);
}
ans[apos[i]] = tree[].type;
if(tree[].num == ) ans[apos[i]] = ;
}
for(i=;i<=n;i++)
printf("%d\n",ans[i]);
}
return ;
}

HDU 5029 Relief grain --树链剖分第一题的更多相关文章

  1. hdu 5029 Relief grain(树链剖分+线段树)

    题目链接:hdu 5029 Relief grain 题目大意:给定一棵树,然后每次操作在uv路径上为每一个节点加入一个数w,最后输出每一个节点个数最多的那个数. 解题思路:由于是在树的路径上做操作, ...

  2. HDU 5029 Relief grain 树链剖分打标记 线段树区间最大值

    Relief grain Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid= ...

  3. hdu_3966_Aragorn's Story(树链剖分裸题)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=3966 题意:给你一棵树,然后给定点之间的路径权值修改,最后单点查询 题解:树链剖分裸题,这里我用树状数 ...

  4. BZOJ 2243 染色 | 树链剖分模板题进阶版

    BZOJ 2243 染色 | 树链剖分模板题进阶版 这道题呢~就是个带区间修改的树链剖分~ 如何区间修改?跟树链剖分的区间询问一个道理,再加上线段树的区间修改就好了. 这道题要注意的是,无论是线段树上 ...

  5. hdu_5029_relief grain(树链剖分)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=5029 题意:给你一个树,然后给你两点,将这两点之间的点涂上颜色,问涂色最多的那个颜色是什么,如果数量相 ...

  6. HDU5029--Relief grain (树链剖分+线段树 )

    题意:n个点构成的无根树,m次操作, 对于操作 x y z, 表示 x 到 y 路径上的 每个点 加一个 z 数字,可重复加.最后输出每个点 加的次数最多的那个数字,如果没有输出0. 赤裸裸的树链剖分 ...

  7. HDU 4366 Successor(树链剖分+zkw线段树+扫描线)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=4366 [题目大意] 有一个公司,每个员工都有一个上司,所有的人呈树状关系,现在给出每个人的忠诚值和 ...

  8. HDU 5044 Tree(树链剖分)

    HDU 5044 Tree field=problem&key=2014+ACM%2FICPC+Asia+Regional+Shanghai+Online&source=1&s ...

  9. 洛谷 P3384 树链剖分(模板题)

    题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操作2: 格式 ...

随机推荐

  1. 用EF6更新数据库时出现外键错误解决方式

    在“Package Manager Console”中执行update-database命令,出现异常信息: Introducing FOREIGN KEY constraint 'FK_dbo.Pr ...

  2. DOM LOAD测试笔记

    DOM时间:1823ms LOAD时间:4912ms COMP时间:5427ms 1585 4757 5650 1859 3487 3910 1600 4648 5099 1610 4428 4878 ...

  3. Exchange 2013 、Lync 2013、SharePoint 2013 二

    上一篇简单介绍了安装过程,本篇主要集成 上一篇文章有关于头像的显示问题,engineer  给出了一个连接,介绍了Exchange和Lync的集成过程,根据介绍都配制了一遍. 一.Exchange 和 ...

  4. TreeView递归绑定无限分类数据

    TreeView递归绑定无限分类数据 实现一个动态绑定,无限级分类数据时,需要将数据绑定到TreeView控件,分类表的结构是这样的: 字段 类型 Id int ParentId int Name N ...

  5. CSS3选择器(二)--表单

    :enabled 选择可用状态的表单元素 :disabled 选择不可用状态的表单元素 :checked 复选框.单选框选中状态的选项 ::selection 用来匹配突出显示的文本(用鼠标选择文本时 ...

  6. 高清HDMI编码器|上海视涛科技

    HDMI编码器(E300)简介 HDMI编码器(E300)是上海视涛科技出品的高性能HDMI+VGA编码产品.该HDMI+VGA编码器是上海视涛科技完全自主研发,并适用于VGA.DVI.HDMI等信号 ...

  7. Atitit.atiInputMethod v2词库清理策略工具    q229

    Atitit.atiInputMethod v2词库清理策略工具    q229 1.1. Foreigncode 外码清理1 1.2. 垃圾词澄清1 1.1. Foreigncode 外码清理 On ...

  8. Force.com微信开发系列(七)OAuth2.0网页授权

    OAuth是一个开放协议,允许用户让第三方应用以安全且标准的方式获取该用户在某一网站上存储的私密资源(如用户个人信息.照片.视频.联系人列表),而无须将用户名和密码提供给第三方应用.本文将详细介绍OA ...

  9. IOS沙盒

    可以先在程序打印沙盒路径: NSLog(@"路径%@",NSHomeDirectory()); ------------------------------------------ ...

  10. iOS-多线程--(pthread/NSThread/GCD/NSOperation)--总结

    零.线程的注意点(掌握) .不要同时开太多的线程(~3条线程即可,不要超过5条) .线程概念 > 主线程 : UI线程,显示.刷新UI界面,处理UI控件的事件 > 子线程 : 后台线程,异 ...