Subject description:
N points, form a tree structure. There are M times issuing, selecting two points each x, y for x to y on the path (including x, y ) of each point sent a bag Z types of items. After all issued, each point store up to what kind of items.
Input formats:
The first row of numbers N, M
the next N-1 lines of two numbers a, b, denotes a and b there is an edge between
and then the next M rows, each row of three numbers x, y, z If that
Output formats:
Output is N lines
for each i the digital representation of the row i point is stored items which most, if there is
the same number of a variety of articles, the minimum output number. If an item is no point output 0 .
Example:
Sample input:
20 50
8 6
10 6
18 6
20 10
7 20
2 18
19 8
1 6
14 20
16 10
13 19
3 14
17 18
11 19
4 11
15 14
5 18
9 10
12 15
11 14 87
12 1 87
14 3 84
17 2 36
6 5 93
17 6 87
10 14 93
5 16 78
6 15 93
15 5 16
11 8 50
17 19 50
5 4 87
15 20 78
1 17 50
20 13 87
7 15 22
16 11 94
19 8 87
18 3 93
13 13 87
2 1 87
2 6 22
5 20 84
10 12 93
18 12 87
16 10 93
8 17 93
14 7 36
7 4 22
5 9 87
13 10 16
20 11 50
9 16 84
10 17 16
19 6 87
12 2 36
20 9 94
9 2 84
14 1 94
5 5 94
8 17 16
12 8 36
20 17 78
12 18 50
16 8 94
2 19 36
10 18 36
14 19 50
4 12 50
(A bit long ......)
Sample output:
87
36
84
22
87
87
22
50
84
87
50
36
87
93
36
94
16
87
50
50
Data range and tips:
1≤N,M≤100000
1≤a,b,x,y≤N
1≤z≤109
answer:
看到这道题我首先想到了这道题:BZOJ3631。
对于上面这道题,如果你还没有思路的话可以看一下这篇博客:[BZOJ3631]:[JLOI2014]松鼠的新家(LCA+树上差分)。
然后,我就立马想到了先求出LCA然后进行树上差分,但是这两道题的区别在于,这道题的物品种类不止一个,而且数还不小,显然不能单纯的用树上差分来解决。
于是考虑用权值线段树维护,先将物品种类排序,然后看利用树上差分更新权值线段树,之后递归合并统计答案即可。
代码时刻:
#include<bits/stdc++.h> using namespace std; struct rec//存边 { int nxt; int to; }e[200000]; struct qwq//存操作 { int x; int y; int z; }question[100001]; int head[100001],cnt; int fa[100001][20]; int root[100001],trfal[10000001],trsum[10000001],ls[10000001],rs[10000001],sum,tot; int dfsv[100001]; int depth[100001]; int que[100001]; bool cmp(qwq a,qwq b){return a.z<b.z;}//按物品排序问题 void add(int x,int y)//建边 { e[++cnt].nxt=head[x]; e[cnt].to=y; head[x]=cnt; } void dfs(int x)//dfs预处理父亲和深度 { dfsv[++dfsv[0]]=x; for(int i=head[x];i;i=e[i].nxt) if(e[i].to!=fa[x][0]) { fa[e[i].to][0]=x; depth[e[i].to]=depth[x]+1; for(int j=1;j<=18;j++) fa[e[i].to][j]=fa[fa[e[i].to][j-1]][j-1]; dfs(e[i].to); } } int LCA(int x,int y)//倍增求LCA { if(depth[x]<depth[y])swap(x,y); for(int i=18;i>=0;i--) if(depth[fa[x][i]]>=depth[y])x=fa[x][i]; if(x==y)return x; for(int i=18;i>=0;i--) if(fa[x][i]!=fa[y][i]) { x=fa[x][i]; y=fa[y][i]; } return fa[x][0]; } void pushup(int x) { trfal[x]=max(trfal[ls[x]],trfal[rs[x]]);//维护的权值 trsum[x]=(trfal[ls[x]]>=trfal[rs[x]])?trsum[ls[x]]:trsum[rs[x]];//哪种物品 } void insert(int &x,int k,int fl,int l,int r) { if(!x)x=++tot; if(l==r) { trfal[x]+=fl; trsum[x]=que[l]; return; } int mid=(l+r)>>1; if(k<=mid)insert(ls[x],k,fl,l,mid); else insert(rs[x],k,fl,mid+1,r); pushup(x); } void ask(int &x,int fl,int l,int r) { if(!fl)return; if(!x) { x=fl; return; } if(l==r) { trfal[x]+=trfal[fl]; return; } int mid=(l+r)>>1; ask(ls[x],ls[fl],l,mid); ask(rs[x],rs[fl],mid+1,r); pushup(x); } int main() { int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)root[i]=i; tot=n; for(int i=1;i<n;i++) { int a,b; scanf("%d%d",&a,&b); add(a,b); add(b,a); } depth[1]=1; dfs(1); for(int i=1;i<=m;i++) scanf("%d%d%d",&question[i].x,&question[i].y,&question[i].z); sort(question+1,question+m+1,cmp); for(int i=1;i<=m;i++) { int lca=LCA(question[i].x,question[i].y); if(question[i].z>question[i-1].z)que[++sum]=question[i].z; insert (root [question [i] .x], sum, 1,1, m); // tree differential operation insert(root[question[i].y],sum,1,1,m); insert(root[lca],sum,-1,1,m); if(lca!=1)insert(root[fa[lca][0]],sum,-1,1,m); } for(int i=n;i>1;i--) ask(root[fa[dfsv[i]][0]],root[dfsv[i]],1,m); for(int i=1;i<=n;i++) printf("%d\n",trsum[root[i]]); return 0; }
rp ++