Bzoj 3307 雨天的尾巴

3307: 雨天的尾巴

Time Limit: 10 Sec  Memory Limit: 128 MB

Description

N个点,形成一个树状结构。有M次发放,每次选择两个点x,y
对于x到y的路径上(含x,y)每个点发一袋Z类型的物品。完成
所有发放后,每个点存放最多的是哪种物品。

Input

第一行数字N,M
接下来N-1行,每行两个数字a,b,表示a与b间有一条边
再接下来M行,每行三个数字x,y,z.如题

Output

 

输出有N行
每i行的数字表示第i个点存放最多的物品是哪一种,如果有
多种物品的数量一样,输出编号最小的。如果某个点没有物品
则输出0

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

Sample Output

87
36
84
22
87
87
22
50
84
87
50
36
87
93
36
94
16
87
50
50


1<=N,M<=100000
1<=a,b,x,y<=N
1<=z<=10^9
 
 solution:
      这题其实很好想,利用差分思想在x,y的权值线段树里z的位置上+1,lca和fa[lca]的位置上-1,每次合并一下线段树就好。
 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 #define mid (l+r>>1)
 7 #define N 100010
 8 int read() {
 9     int s=0,f=1;
10     char ch=getchar();
11     for( ; ch<'0'||ch>'9'; f=(ch=='-')?-1:f,ch=getchar()) ;
12     for( ; ch>='0'&&ch<='9'; s=s*10+(ch^48),ch=getchar()) ;
13     return s*f;
14 }
15 int n,m,tot,cnt,num;
16 int r[N],p[19][N],deep[N],root[N],Hash[N];
17 int mx[N*50],ord[N*50],ls[N*50],rs[N*50];
18 struct node {
19     int X,Y,Z;
20     friend bool operator < (node a,node b) {return a.Z<b.Z;}
21 } q[N];
22 struct EDGE{int to,next;} c[N<<1];
23 void add(int a,int b) {
24     c[++tot]=(EDGE){b,r[a]},r[a]=tot;
25 }
26 void dfs(int x) {
27     for(int i=r[x]; ~i; i=c[i].next) if(c[i].to!=p[0][x]) p[0][c[i].to]=x,deep[c[i].to]=deep[x]+1,dfs(c[i].to);
28 }
29 int lca(int a,int b) {
30     if(deep[a]<deep[b]) swap(a,b);
31     for(int i=18; i>=0; --i) if(deep[p[i][a]]>=deep[b]) a=p[i][a];
32     if(a==b) return a;
33     for(int i=18; i>=0; --i) if(p[i][a]!=p[i][b]) a=p[i][a],b=p[i][b];
34     return p[0][a];
35 }
36 void pushup(int x) {
37     mx[x]=max(mx[ls[x]],mx[rs[x]]);
38     ord[x]=(mx[ls[x]]>=mx[rs[x]])?ord[ls[x]]:ord[rs[x]];
39 }
40 void update(int &x,int a,int b,int l,int r) {
41     if(!x) x=++cnt;
42     if(l==r) {mx[x]+=b,ord[x]=Hash[l];return ;}
43     if(a<=mid) update(ls[x],a,b,l,mid);
44     else update(rs[x],a,b,mid+1,r);
45     pushup(x);
46 }
47 void Merge(int &a,int b,int l,int r) {
48     if(!b) return ;
49     if(!a) {a=b;return ;}
50     if(l==r) {mx[a]+=mx[b];return ;}
51     Merge(ls[a],ls[b],l,mid),Merge(rs[a],rs[b],mid+1,r);
52     pushup(a);
53 }
54 void M(int u) {for(int i=r[u]; ~i; i=c[i].next) if(c[i].to!=p[0][u]) M(c[i].to),Merge(root[u],root[c[i].to],1,m);}
55 int main() {
56     n=read(),m=read();
57     memset(r,0xff,sizeof(r));
58     for(int i=1; i<=n; ++i)  root[i]=++cnt;
59     for(int a,b,i=1; i<n; ++i) a=read(),b=read(),add(a,b),add(b,a);
60     deep[1]=1,dfs(1);
61     for(int j=1; (1<<j)<=n; j++) for(int i=1; i<=n; ++i) p[j][i]=p[j-1][p[j-1][i]];
62     for(int i=1; i<=m; ++i) q[i].X=read(),q[i].Y=read(),Hash[i]=q[i].Z=read();
63     sort(q+1,q+m+1);  sort(Hash+1,Hash+m+1); num=unique(Hash+1,Hash+m+1)-Hash;
64     for(int a,b,LCA,d=0,i=1; i<=m; ++i) {
65         a=q[i].X,b=q[i].Y,LCA=lca(a,b);
66         d=lower_bound(Hash+1,Hash+num,q[i].Z)-Hash;
67         update(root[a],d,1,1,m),update(root[b],d,1,1,m),update(root[LCA],d,-1,1,m);
68         if(LCA!=1)  update(root[p[0][LCA]],d,-1,1,m);
69     } M(1);
70     for(int i=1; i<=n; ++i) printf("%d\n",ord[root[i]]);
71     return 0;
72 }

 

posted @ 2017-10-30 11:45  Forever_goodboy  阅读(159)  评论(0编辑  收藏  举报