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. R语言中字符串的拼接操作

    在R语言中 paste 是一个很有用的字符串处理函数,可以连接不同类型的变量及常量. 函数paste的一般使用格式为: paste(..., sep = " ", collapse ...

  2. selenium测试(Java)--告警框处理(十四)

    下面代码中介绍了告警框的处理方法 package com.test.alerthandle; import org.openqa.selenium.By; import org.openqa.sele ...

  3. 第三百零五节,Django框架,Views(视图函数),也就是逻辑处理函数里的各种方法与属性

    Django框架,Views(视图函数),也就是逻辑处理函数里的各种方法与属性 Views(视图函数)逻辑处理,最终是围绕着两个对象实现的 http请求中产生两个核心对象: http请求:HttpRe ...

  4. WAMP环境下配置虚拟主机

    1.编辑httpd.conf,查找#Include conf/extra/httpd-vhosts.conf,把前面注释符号“#”删掉 2.编辑httpd-vhosts.conf文件, <Vir ...

  5. electron-searchMovies

    之前学了electron,前段时间又学了一下vue,为了增加熟练度决定将两者结合做个有趣的东西.想来想去最后决定将原来用 PyQt 写的MovieHeavens重新写一遍,使用electron-vue ...

  6. JavaScript 事件参考手册

    事件通常与函数配合使用,这样就可以通过发生的事件来驱动函数执行. 事件句柄 HTML 4.0 的新特性之一是有能力使 HTML 事件触发浏览器中的动作(action),比如当用户点击某个 HTML 元 ...

  7. JS中函数声明与函数表达式的异同

    相同点 注:函数声明和函数表达式的相同点包括但不限于以下几点 函数是一个值,所以和其他值一样,函数也可以进行被输出.被赋值.作为参数传给其他函数等相关操作,不管函数是以什么方式被定义的,当然和其他值的 ...

  8. Ubuntu 安装 Oracle11gR2:'install' of makefile '/home/oracle/app/oracle/product/11.2.0/dbhome_1/ctx/lib/ins_ctx.mk'

    网上包括官方,就是教给你如何安装依赖包什么的:libstdc++5,但很麻烦:既要下载找相关的包,还不一定能安装的上. 其实,仅仅是为了安装,直接从二进制的deb包里,解压一个 “libstdc++. ...

  9. CSS实现圆角的方法

    <style type="text/css"> body,p,div {margin:0;padding:0;} .Box {margin:10px auto;widt ...

  10. UVA 11542 - Square(高斯消元)

    UVA 11542 - Square 题目链接 题意:给定一些数字.保证这些数字质因子不会超过500,求这些数字中选出几个,乘积为全然平方数,问有几种选法 思路:对每一个数字分解成质因子后.发现假设要 ...