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.
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.
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
题意
给你一棵树,每次可以给一条路径分配一个值,值可以叠加,最后输出每个点被分配最多的那个值。
题解
我们先考虑一个问题,如果是在一个序列里,每次给你一个区间(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 }