J - Relief grain HDU - 5029

Relief grain

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 100000/100000 K (Java/Others)
Total Submission(s): 3246    Accepted Submission(s): 955


题目链接

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

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

Hint

For the first test case, the relief grain in the 1st village is {1, 2}, and the relief grain in the 2nd village is {1, 2, 2}.

Source

2014 ACM/ICPC Asia Regional Guangzhou Online

题意

给你一棵树,每次可以给一条路径分配一个值,值可以叠加,最后输出每个点被分配最多的那个值。

题解

我们先考虑一个问题,如果是在一个序列里,每次给你一个区间(l,r),问每个点最后被多少个区间覆盖。

这道题是一道比较经典的扫描线的题,如果不会我来讲讲:

对于每个区间(l,r),我们把他拆成两个点,(l,1) 和(r+1,-1),(1代码左端点,-1表示右端点),并将其排序。然后假想有一条扫描线从左扫到右,每次碰到一个左端点答案加一,碰到右端点答案减一。

边扫边统计答案,答案就是到当前点,有多少个左端点还没有碰到右端点。

这样可能有点抽象自己可以模拟几遍,应该还是能想出来的。

那么和这道题有什么关系呢? 当然有关系啦,不然我为什么会将呢?

1.我们加一颗权值线段树,对于每个区间我们增加了一维权值来确定,即(l,r,val)表示l~r赋值为val,那么还是如上一样扫描,然后答案加一的步骤改成给线段树点val加上1,

这样每个点的答案就是线段树中最大值的位置。

2.但是这是在树上,所以树链剖分将他变成一个连续序列即可。

代码

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define ll long long
  4 #define N 200050
  5 struct Edge{int from,to,s;}edges[N<<1];
  6 struct Query
  7 {
  8   int x,val,id;
  9   bool operator <(const Query&b)const
 10   {return x<b.x;}
 11 }a[N<<2];
 12 struct Tree{int l,r,mx,wmx;}tr[N<<2];
 13 int n,m,num,ans[N];
 14 int tot,last[N];
 15 int cnt,fa[N],dp[N],size[N],son[N],rk[N],kth[N],top[N];
 16 template<typename T>void read(T&x)
 17 {
 18   ll k=0; char c=getchar();
 19   x=0;
 20   while(!isdigit(c)&&c!=EOF)k^=c==‘-‘,c=getchar();
 21   if (c==EOF)exit(0);
 22   while(isdigit(c))x=x*10+c-‘0‘,c=getchar();
 23   x=k?-x:x;
 24 }
 25 void read_char(char &c)
 26 {while(!isalpha(c=getchar())&&c!=EOF);}
 27 void AddEdge(int x,int y)
 28 {
 29   edges[++tot]=Edge{x,y,last[x]};
 30   last[x]=tot;
 31 }
 32 void dfs1(int x,int pre)
 33 {
 34   fa[x]=pre;
 35   dp[x]=dp[pre]+1;
 36   size[x]=1;
 37   son[x]=0;
 38   for(int i=last[x];i;i=edges[i].s)
 39     {
 40       Edge &e=edges[i];
 41       if (e.to==pre)continue;
 42       dfs1(e.to,x);
 43       size[x]+=size[e.to];
 44       if (size[e.to]>size[son[x]])
 45     son[x]=e.to;
 46     }
 47 }
 48 void dfs2(int x,int y)
 49 {
 50   rk[x]=++cnt;
 51   kth[cnt]=x;
 52   top[x]=y;
 53   if (son[x]==0)return;
 54   dfs2(son[x],y);
 55   for(int i=last[x];i;i=edges[i].s)
 56     {
 57       Edge e=edges[i];
 58       if (e.to==fa[x]||e.to==son[x])continue;
 59       dfs2(e.to,e.to);
 60     }
 61 }
 62 void push_up(Tree &c,Tree a,Tree b)
 63 {
 64   c.mx=max(a.mx,b.mx);
 65   c.wmx=c.mx==a.mx?a.wmx:b.wmx;
 66 }
 67 void bt(int x,int l,int r)
 68 {
 69   tr[x]=Tree{l,r,0,0};
 70   if (l==r){tr[x].wmx=l;return;}
 71   int mid=(l+r)>>1;
 72   bt(x<<1,l,mid);
 73   bt(x<<1|1,mid+1,r);
 74 }
 75 void update(int x,int p,int tt)
 76 {
 77   if (p<=tr[x].l&&tr[x].r<=p)
 78     {
 79       tr[x].mx+=tt;
 80       tr[x].wmx=tr[x].l;
 81       return;
 82     }
 83   int mid=(tr[x].l+tr[x].r)>>1;
 84   if (p<=mid)update(x<<1,p,tt);
 85   if (mid<p)update(x<<1|1,p,tt);
 86   push_up(tr[x],tr[x<<1],tr[x<<1|1]);
 87 }
 88 void change(int x,int y,int tt)
 89 {
 90   int fx=top[x],fy=top[y];
 91   while(fx!=fy)
 92     {
 93       if (dp[fx]<dp[fy])swap(x,y),swap(fx,fy);
 94       a[++num]=Query{rk[fx],tt,1};
 95       a[++num]=Query{rk[x]+1,tt,-1};
 96       x=fa[fx];fx=top[x];
 97     }
 98   if (dp[x]<dp[y])swap(x,y);
 99   a[++num]=Query{rk[y],tt,1};
100   a[++num]=Query{rk[x]+1,tt,-1};
101 }
102 void work()
103 {
104   read(n); read(m);
105   if (n==0)exit(0);
106   for(int i=1;i<=n-1;i++)
107     {
108       int x,y;
109       read(x); read(y);
110       AddEdge(x,y);
111       AddEdge(y,x);
112     }
113   dfs1(1,0);
114   dfs2(1,1);
115   bt(1,0,100005);
116   for(int i=1;i<=m;i++)
117     {
118       int x,y,tt;
119       read(x); read(y); read(tt);
120       change(x,y,tt);
121     }
122   sort(a+1,a+num+1);
123   for(int i=1;i<=num-1;i++)
124     {
125       int l=a[i].x;
126       update(1,a[i].val,a[i].id);
127       while(a[i+1].x==a[i].x)
128     //update(1,a[++i].val,a[i].id);
129     i++,update(1,a[i].val,a[i].id);
130
131       for(int j=l;j<a[i+1].x;j++)
132     ans[kth[j]]=tr[1].wmx;
133     }
134   for(int i=1;i<=n;i++)printf("%d\n",ans[i]);
135 }
136 void clear()
137 {
138   tot=0; cnt=0; num=0;
139   memset(last,0,sizeof(last));
140   memset(ans,0,sizeof(ans));
141 }
142 int main()
143 {
144 #ifndef ONLINE_JUDGE
145   freopen("aa.in","r",stdin);
146 #endif
147   while(1)
148     {
149       clear();
150       work();
151     }
152 }

原文地址:https://www.cnblogs.com/mmmqqdd/p/10793675.html

时间: 2024-10-12 08:10:24

J - Relief grain HDU - 5029的相关文章

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

题目链接:hdu 5029 Relief grain 题目大意:给定一棵树,然后每次操作在uv路径上为每一个节点加入一个数w,最后输出每一个节点个数最多的那个数. 解题思路:由于是在树的路径上做操作,所以基本就是树链剖分了.仅仅只是曾经是用一个数组就可以维护值,这题要用 一个vector数组记录.过程中用线段树维护最大值. #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #i

HDU 5029 Relief grain(离线+线段树+启发式合并)(2014 ACM/ICPC Asia Regional Guangzhou Online)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5029 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 disa

HDU 5029 Relief grain

Relief grain Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 100000/100000 K (Java/Others)Total Submission(s): 867    Accepted Submission(s): 221 Problem Description The soil is cracking up because of the drought and the rabbit kingdom is fa

树链剖分 [HDU 5029] Relief grain

Relief grain Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 100000/100000 K (Java/Others) Total Submission(s): 1254    Accepted Submission(s): 299 Problem Description The soil is cracking up because of the drought and the rabbit kingdom is

hdu 5029 Relief grain(树链剖分好题)

Relief grain Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 100000/100000 K (Java/Others) Total Submission(s): 295    Accepted Submission(s): 66 Problem Description The soil is cracking up because of the drought and the rabbit kingdom is fa

HDU 5029 树链剖分

Relief grain Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 100000/100000 K (Java/Others) Total Submission(s): 861    Accepted Submission(s): 219 Problem Description The soil is cracking up because of the drought and the rabbit kingdom is f

HDU 5029 Relief grain(树链剖分)

题目链接~~> 做题感悟:这题真的很巧妙,分析了一下午才分析懂其中的奥妙,感觉收获很大. 解题思路: 首先需要树链剖分一下,把树剖分成链.然后的思想和HDU 5044 差不多,只不过这个不用数组遍历,而是用线段树代替数组.如果你在[ a ,b ] 区间染色,则可以让 a 节点加上这种颜色,让 b + 1 减去这种颜色,这样最后遍历一下数组就可以了,但是这题每个节点可以染许多颜色,所以不可以和数组一样只遍历一次,我们可以把那些点弄到线段树上,这样只需要在线段树上更新点就可以了 ,每一次得到的颜色一

HDU 5029 Relief grain --熟练剖分第一题

题意:给一棵树,每次给两个节点间的所有节点发放第k种东西,问最后每个节点拿到的最多的东西是哪种. 解法:解决树的路径上的修改查询问题一般用到的是树链剖分+线段树,以前不会写,后来学了一下树链剖分,感觉也不是很难,就是把整个数分成很多链,然后一条重链上的点在线段树中位置是连续的,这样使得更新和查询时更加便利. 这个题目中线段树应该维护的是种类,每次对u-v发放k时,可以让u处+k,v+1处-k,把这些都离线存起来,然后枚举1~n,分别把自己该做的操作都做了,然后统计的时候tree[1].type就

Hdu 5029 Relief grain(熟练剖分)

题目大意: 给出一棵树. 然后有m个操作,每个操作都在两点的路径上分配不同的粮食. 最后要求输出所有村庄有的最多的粮食的种类. 思路分析: 一眼就看得出来是树链剖分的题目. 现在的问题就是,每一次操作,如何维护每个点的最多的食物编号,以及最多的食物的数量.要记录这两个值是肯定的. 首先可以想到将所有的操作按照z排序.这样每一回合操作,称一回合为处理同一种颜色.一回合结束之后,后面的操作就不会影响前面取得的最大值.因为后面的操作的食物的种类不一样,是不可以再继续累加的. 然后可以发现一个规律,就是