BZOJ 3307: 雨天的尾巴 线段树合并 树上差分

来源:互联网 发布:淘宝的被骗了怎么办 编辑:程序博客网 时间:2024/04/30 23:16

3307: 雨天的尾巴

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 610  Solved: 254
[Submit][Status][Discuss]

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

对每个节点建权值线段树,树上差分再合并就行了


树上差分就不多说了


这两天发现线段树合并真是个好东西

每个节点的答案递归可以由子树合并而来


听说好像可以链剖? 不会 嘿嘿


#include<cmath>#include<ctime>#include<cstdio>#include<cstring>#include<cstdlib>#include<iostream>#include<algorithm>#include<iomanip>#include<vector>#include<string>#include<bitset>#include<queue>#include<map>#include<set>using namespace std;inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}void print(int x){if(x<0)putchar('-'),x=-x;if(x>=10)print(x/10);putchar(x%10+'0');}const int N=100100;int n,m,maxn;int ecnt,last[N];struct EDGE{int to,nt;}e[N<<1];inline void add(int u,int v){e[++ecnt]=(EDGE){v,last[u]};last[u]=ecnt;}struct changeopt{int u,v,val;friend bool operator <(const changeopt &x,const changeopt &y){return x.val<y.val;}}o[N];int fa[N][18],d[N],dfn[N],pos[N],ref[N],root[N],ans[N],cnt;void dfs(int u){dfn[u]=++cnt;pos[cnt]=u;for(int i=1;(1<<i)<=d[u];++i)fa[u][i]=fa[fa[u][i-1]][i-1];for(int i=last[u];i;i=e[i].nt){if(fa[u][0]==e[i].to)continue;fa[e[i].to][0]=u;d[e[i].to]=d[u]+1;dfs(e[i].to);}}inline int getlca(int u,int v){if(d[u]<d[v])swap(u,v);int len=d[u]-d[v];for(int i=0;(1<<i)<=len;++i)if(len&(1<<i))u=fa[u][i];if(u==v)return u;for(int i=17;i>=0;--i)if(fa[u][i]^fa[v][i])u=fa[u][i],v=fa[v][i];return fa[u][0];}struct val_tree{int w,mx,ls,rs;}tr[N<<6];inline void pushup(int k){tr[k].mx=max(tr[tr[k].ls].mx,tr[tr[k].rs].mx);}inline void modify(int &k,int x,int l,int r,int val,int p){k=++cnt;tr[k].w=tr[x].w+p;if(l==r){tr[k].mx=tr[k].w;return ;}int mid=(l+r)>>1;tr[k].ls=tr[x].ls;tr[k].rs=tr[x].rs;val<=mid?modify(tr[k].ls,tr[x].ls,l,mid,val,p):modify(tr[k].rs,tr[x].rs,mid+1,r,val,p);pushup(k);}int merge(int x,int y,int l,int r){if(!x)return y;if(!y)return x;int mid=(l+r)>>1;tr[x].w=tr[x].w+tr[y].w;if(l==r){tr[x].mx=tr[x].w;return x;}tr[x].ls=merge(tr[x].ls,tr[y].ls,l,mid);tr[x].rs=merge(tr[x].rs,tr[y].rs,mid+1,r);pushup(x);return x;}int query(int k,int l,int r){if(!tr[k].w)return 0;if(l==r)return l;int mid=(l+r)>>1;if(tr[tr[k].ls].mx==tr[k].mx)return query(tr[k].ls,l,mid);return query(tr[k].rs,mid+1,r);}int main(){n=read();m=read();register int i,u,v,val=0,lca,falca;for(i=1;i<n;++i){u=read();v=read();add(u,v);add(v,u);}for(i=1;i<=m;++i){o[i].u=read();o[i].v=read();o[i].val=read();}dfs(1);sort(o+1,o+1+m);maxn=1;ref[1]=o[1].val;for(i=2;i<=m;++i){if(o[i].val^ref[maxn])maxn++;ref[maxn]=o[i].val;}for(i=1;i<=m;++i){u=o[i].u;v=o[i].v;if(o[i].val^o[i-1].val)val++;lca=getlca(u,v);falca=fa[lca][0];modify(root[u],root[u],1,maxn,val,1);modify(root[v],root[v],1,maxn,val,1);modify(root[lca],root[lca],1,maxn,val,-1);if(falca)modify(root[falca],root[falca],1,maxn,val,-1);}for(i=n;i;i--){root[fa[pos[i]][0]]=merge(root[fa[pos[i]][0]],root[pos[i]],1,maxn);ans[pos[i]]=query(root[pos[i]],1,maxn);}for(i=1;i<=n;++i)print(ref[ans[i]]),puts("");return 0;}