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个点存放最多的物品是哪一种,如果有
多种物品的数量一样,输出编号最小的。如果某个点没有物品
则输出0Sample 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 }