http://acm.hdu.edu.cn/showproblem.php?pid=5029

Relief grain

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 100000/100000 K (Java/Others)

Total Submission(s): 405    Accepted Submission(s): 95
Problem Description
The soil is cracking up because of the drought and the rabbit kingdom is facing a serious famine. The RRC(Rabbit Red Cross) organizes the distribution of relief grain in the disaster area.



We can regard the kingdom as a tree with n nodes and each node stands for a village. The distribution of the relief grain is divided into m phases. For each phases, the RRC will choose a path of the tree and distribute some relief grain of a certain type for
every village located in the path.



There are many types of grains. The RRC wants to figure out which type of grain is distributed the most times in every village.
 
Input
The input consists of at most 25 test cases.



For each test case, the first line contains two integer n and m indicating the number of villages and the number of phases.



The following n-1 lines describe the tree. Each of the lines contains two integer x and y indicating that there is an edge between the x-th village and the y-th village.

  

The following m lines describe the phases. Each line contains three integer x, y and z indicating that there is a distribution in the path from x-th village to y-th village with grain of type z. (1 <= n <= 100000, 0 <= m <= 100000, 1 <= x <= n, 1 <= y <= n,
1 <= z <= 100000)



The input ends by n = 0 and m = 0.
 
Output
For each test case, output n integers. The i-th integer denotes the type that is distributed the most times in the i-th village. If there are multiple types which have the same times of distribution, output the minimal one. If there
is no relief grain in a village, just output 0.
 
Sample Input
2 4
1 2
1 1 1
1 2 2
2 2 2
2 2 1
5 3
1 2
3 1
3 4
5 3
2 3 3
1 5 2
3 3 3
0 0
 
Sample Output
1
2
2
3
3
0
2

题意:给出一棵树,然后有一系列的操作,每次操作有a,b,c代表在a到b的路径上的每个点都给一个c类型的数字;最后问所有操作完成后树上的每个节点拥有的数量最多的类型是多少,如果存在多个输出较小类型的数字;

分析:首先这种在树上的操作,很容易想到是树链剖分的题目,但是具体该怎么写呢:先不考虑树的问题,可以把题意抽象出一个普通的连续区间【1,n】,然后在不同区间进行分配东西,最后问每个点的结果,对于区间【L,R】上分配一个数字Z,那么就在L位置上标记+Z,代表从此时以后的每个节点都拥有一个Z,然后在R+1的位置上标记一个-Z,代表从该节点开始没有分配Z这个数字;所以先把m个操作记录下来,对于每个标记的节点,可以用一个vector容器记录所标记的东西,接下来我们可以建立一个权值线段树区间【1,100000】;每个点分别代表数字Z的类型,px数组代表每个类型数字当前出现的次数;tree[i].maxi代表i区间的最大值,从左向右遍历区间【1,n】,对于每个节点更新px的值,如果标记是+Z,则px[z]++;否则px[-z]--;然后query即可;

树链剖分也是同样的道理,轻重链的划分不详说了,对于一个树上的两点<u,v>,把它转化为多条连续的子链利用线段树操作即可;具体程序如下:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include"stdio.h"
#include"string.h"
#include"iostream"
#include"map"
#include"string"
#include"queue"
#include"stdlib.h"
#include"math.h"
#define M 110009
#define eps 1e-10
#define inf 1000000000
#define mod 1000000000
#define INF 1000000000
using namespace std;
struct node
{
int u,v,next;
}edge[M*2];
struct Lnode
{
int v;
Lnode(int vv)
{
v=vv;
}
};
vector<Lnode>e[M];
int t,pos,head[M],son[M],fa[M],num[M],top[M],ID,deep[M],p[M],fp[M],px[M];
void init()
{
t=pos=0;
memset(head,-1,sizeof(head));
memset(son,-1,sizeof(son));
memset(fa,-1,sizeof(fa));
}
void add(int u,int v)
{
edge[t].u=u;
edge[t].v=v;
edge[t].next=head[u];
head[u]=t++;
}
void dfs(int u,int f,int d)
{
deep[u]=d;
fa[u]=f;
num[u]=1;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(v==f)continue;
dfs(v,u,d+1);
num[u]+=num[v];
if(son[u]==-1||num[son[u]]<num[v])
son[u]=v;
}
}
void getpos(int u,int sp)
{
top[u]=sp;
p[u]=pos++;
fp[p[u]]=u;
if(son[u]==-1)return;
getpos(son[u],sp);
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(v==fa[u]||v==son[u])continue;
getpos(v,v);
}
}
/**********以上是划分轻重链**************/
struct Tree
{
int l,r,maxi;
}tree[M*4];
void make(int l,int r,int i)//线段树建树操作
{
tree[i].l=l;
tree[i].r=r;
if(l==r)
{
tree[i].maxi=0;
return ;
}
int mid=(l+r)/2;
make(l,mid,i*2);
make(mid+1,r,i*2+1);
tree[i].maxi=max(tree[i*2].maxi,tree[i*2+1].maxi);
}
void updata(int p,int q,int i)//单点更新操作
{
if(tree[i].l==p&&tree[i].r==p)
{
tree[i].maxi=q;
return;
}
int mid=(tree[i].l+tree[i].r)/2;
if(p<=mid)updata(p,q,i*2);
else updata(p,q,i*2+1);
tree[i].maxi=max(tree[i*2].maxi,tree[i*2+1].maxi);
}
void query(int l,int r,int i)//区间查找最大值对应的标,若有多个查找编号最小的记录到ID中
{
if(tree[i].maxi<tree[1].maxi)
return;
if(tree[i].l==tree[i].r)
{
if(tree[i].l<ID)
ID=tree[i].l;
return;
}
int mid=(tree[i].l+tree[i].r)/2;
if(r<=mid)
query(l,r,i*2);
else if(l>mid)
query(l,r,i*2+1);
else
{
query(l,mid,i*2);
query(mid+1,r,i*2+1);
}
}
void Insert(int u,int v,int w)//树与线段树的转化操作
{
int f1=top[u];
int f2=top[v];
while(f1!=f2)
{
if(deep[f1]<deep[f2])
{
swap(f1,f2);
swap(u,v);
}
e[p[f1]].push_back(Lnode(w));
e[p[u]+1].push_back(Lnode(-w));
u=fa[f1];
f1=top[u];
}
if(u==v)
{
e[p[u]].push_back(Lnode(w));
e[p[u]+1].push_back(Lnode(-w));
return;
}
if(deep[u]>deep[v])
swap(u,v);
e[p[u]].push_back(Lnode(w));
e[p[v]+1].push_back(Lnode(-w));
return;
}
int s[M];
int main()
{
int n,m,i,j,a,b,c,u,v;
while(scanf("%d%d",&n,&m),m||n)
{
init();
for(i=0;i<=n;i++)
e[i].clear();
for(i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
dfs(1,1,1);
getpos(1,1);
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&a,&b,&c);
Insert(a,b,c);
}
make(1,100000,1);
memset(px,0,sizeof(px));
for(i=0;i<pos;i++)
{
for(j=0;j<(int)e[i].size();j++)
{
int v=e[i][j].v;
if(v>0)
{
px[v]++;
updata(v,px[v],1);
}
else
{
px[-v]--;
updata(-v,px[-v],1);
}
}
if(tree[1].maxi==0)
{
s[fp[i]]=0;
continue;
}
ID=100000;
query(1,100000,1);
s[fp[i]]=ID;
//printf("%d\n",ID);
}
for(i=1;i<=n;i++)
printf("%d\n",s[i]);
}
return 0;
}



树链剖分+线段树+离线(广州网选赛第八题hdu5029)的更多相关文章

  1. 2019西北工业大学程序设计创新实践基地春季选拔赛 I Chino with Rewrite (并查集+树链剖分+线段树)

    链接:https://ac.nowcoder.com/acm/contest/553/I 思路:离线整棵树,用并查集维护下联通的情况,因为值只有60个,用2的x(1<=x<=60)次方表示 ...

  2. 洛谷P4092 [HEOI2016/TJOI2016]树 并查集/树链剖分+线段树

    正解:并查集/树链剖分+线段树 解题报告: 传送门 感觉并查集的那个方法挺妙的,,,刚好又要复习下树剖了,所以就写个题解好了QwQ 首先说下并查集的方法趴QwQ 首先离线,读入所有操作,然后dfs遍历 ...

  3. 【bzoj3626】[LNOI2014]LCA 树链剖分+线段树

    题目描述 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先.有q次询问,每次询 ...

  4. 【bzoj1959】[Ahoi2005]LANE 航线规划 树链剖分+线段树

    题目描述 对Samuel星球的探险已经取得了非常巨大的成就,于是科学家们将目光投向了Samuel星球所在的星系——一个巨大的由千百万星球构成的Samuel星系. 星际空间站的Samuel II巨型计算 ...

  5. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1153  Solved: 421[Submit][Statu ...

  6. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

    [BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...

  7. BZOJ2243 (树链剖分+线段树)

    Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...

  8. POJ3237 (树链剖分+线段树)

    Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...

  9. bzoj4034 (树链剖分+线段树)

    Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...

随机推荐

  1. 20个优秀的JavaScript 键盘事件处理库

    键盘事件是 Web 开发中最常用的事件之一,通过对键盘事件的捕获和处理可以提高网站的易用性和交互体验.下面,我们向大家介绍收集的20款优秀的 JavaScript 键盘事件处理库,帮助开发人员轻松处理 ...

  2. ubuntu16.04 安装caffe以及python接口

    http://blog.csdn.net/qq_25073253/article/details/72571714http://blog.csdn.net/greed7480/article/deta ...

  3. jquery load ($.load) 事件用法与分析(转)

    首先我们需要清楚的是jquery load方法是对jQuery.ajax()进行封装以方便我们使用的一个方法,当我们需要处理较为复杂的逻辑时候,还是需要用到jQuery.ajax()这个比较全面的方法 ...

  4. 【Java面试题】35 List, Set, Map是否继承自Collection接口?

    Collection是最基本的集合接口,声明了适用于JAVA集合(只包括Set和List)的通用方法. Set 和List 都继承了Conllection:Set具有与Collection完全一样的接 ...

  5. opengl 模板测试 glStencilOp glStencilFunc

    下面来设置蒙板缓存和蒙板测试. 首先我们启用蒙板测试,这样就可以修改蒙板缓存中的值. 下面我们来解释蒙板测试函数的含义: 当你使用glEnable(GL_STENCIL_TEST)启用蒙板测试之后,蒙 ...

  6. hadoop中文官网

    http://hadoop.apache.org/docs/r1.0.4/cn/hdfs_shell.html

  7. Jquery实现$.fn.extend和$.extend函数

    $.fn.extend(   {      method:function(){   }   })   $.extend(   {      method:function(){   }   })

  8. WPF 自定义命令 以及 命令的启用与禁用

    自定义命令:     在WPF中有5个命令类(ApplicationCommands.NavigationCommands.EditingCommands.ComponentCommands 以及 M ...

  9. Spring----Spring Boot Rest的使用方法

    1.下载Google浏览器并安装插件 转载: http://chromecj.com/web-development/2015-03/401/download.html 打开Google浏览器-> ...

  10. ios开发之--使用toolbar调整item之间的间隔

    toolbar的item有很多种样式,其实经常使用的就几种, UIBarButtonSystemItemFixedSpace 木棍:可以理解为固定的长度 UIBarButtonSystemItemFl ...