Description
Pulumi生活在P城的角落,而他的朋友们gjdy,oyski,tutuwai等等生活在P城的靠中心位置。
P城很大,但它拥有优秀的城市结构,同时P城重视文化教育的发展,P城共有n个学校,校与校之间共建立了n-1条交通线路,且两所学校之间存在唯一的连通路径。
P城常常举行各种类型的评比活动,为了节约资金,最终将给某一条路径上的所有学校颁发证书。为了便于描述我们记一次评比活动的结果为(ui,vi,zi)表示路径(ui,vi)上的所有学校获得一个类型为zi的证书。
一个学校若为Zmax类型的学校,则表示它在Zmax类型下的证书数量最多(如果有相同数量的类型,取类型标号最小一个)。
Pulumi收集了本年度所有的评比活动结果,共m次。他很感兴趣所有学校的类型,以了解他朋友们学校的状况,现在他忙于出题,把这个任务交给了你。
Input
第一行,两个整数n,m,如题中所述。
下接n-1行,每行两个整数u,v,表示标号u和v的学校之间有一条直接相连的路。
下接m行,每行三个整数u,v,z,表示一次结果为(u,v,z)的评比活动。
Output
共n行,第i行,一个整数zi,表示标号为i的学校类型为zi。
Sample Input
5 3
1 2
3 1
3 4
5 3
2 3 3
1 5 2
3 3 3
Sample Output
2
3
3
0
2
Data Constraint
对于30%的数据1<=N<=1000,1<=M<=1000
另外在30%的数据满足i-1与i之间有一条直接相连的路
对于100%的数据1<=N<=100000,0<=M<=100000,1<=zi<=10^9
Solution
这个,裸的树剖嘛
用线段树维护每种颜色出现的次数
树剖一波
然后打几个标记
这个可以用vector来搞一搞
Code
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define L rt*2
#define R rt*2+1
using namespace std;
const int N=100005;
struct edge{
int x,y;
} tr[4*N];
int n,i,x,y,z,f1,f2,k,tot,num,cnt,nx[2*N],b[2*N],he[N],m;
int fa[N],h[N],s[N],son[N],d[N],top[N],seq[N],pre[N],dfn[N];
int a[N],c[N],bb[N],nw[N],j,ans[N]; vector<int> g[N];
int read(){
int sum=0;
char c=getchar();
while (c<'0'||c>'9') c=getchar();
while (c>='0'&&c<='9'){
sum=sum*10+c-'0';
c=getchar();}
return sum;
}
inline void add(int x,int y){
nx[++cnt]=he[x];he[x]=cnt;b[cnt]=y;
}
void dfs1(int x){
int i,j;
s[x]=1;
for(i=he[x];i;i=nx[i]){
j=b[i];
if (j==fa[x]) continue;
fa[j]=x; h[j]=h[x]+1;
dfs1(j);
s[x]+=s[j];
if (s[son[x]]<s[j]) son[x]=j;
}
}
void dfs2(int x,int y){
int i,j;
top[seq[dfn[x]=++num]=x]=y;
if (!son[x]) return;
dfs2(son[x],y);
for(i=he[x];i;i=nx[i]){
j=b[i];
if (j==fa[x]||j==son[x]) continue;
dfs2(j,j);}
}
inline void swap(int &x,int &y){x^=y,y^=x,x^=y;}
inline edge update(edge a,edge b){return a.x>=b.x?a:b;}
inline void change(int rt,int l,int r,int x,int y){
if (l==r){
if (tr[rt].x+=y) tr[rt].y=x; else tr[rt].y=0;
return;}
int mid=(l+r)>>1;
if (x<=mid) change(L,l,mid,x,y);
else change(R,mid+1,r,x,y);
tr[rt]=update(tr[L],tr[R]);
}
inline edge find(int rt,int l,int r,int x,int y){
if (l>=x&&r<=y) return tr[rt];
int mid=(l+r)>>1;
if (y<=mid) return find(L,l,mid,x,y);
else if (x>mid) return find(R,mid+1,r,x,y);
else return update(find(L,l,mid,x,mid),find(R,mid+1,r,mid+1,y));
}
bool cmp(int x,int y){return x<y;}
int main(){
freopen("certif.in","r",stdin);
freopen("certif.out","w",stdout);
n=read(),m=read();
fo(i,2,n) add(x=read(),y=read()),add(y,x);
fa[1]=1; s[0]=0; dfs1(1);
dfs2(1,1);
fo(i,1,m){
a[i]=read(),bb[i]=read(),c[i]=read();
d[++d[0]]=c[i];
}
sort(d+1,d+d[0]+1,cmp);
tot=unique(d+1,d+d[0]+1)-d-1;
fo(i,1,m) nw[i]=lower_bound(d+1,d+tot+1,c[i])-d,pre[nw[i]]=c[i];
fo(i,1,m){
x=a[i],y=bb[i],z=nw[i],k=nw[i];
f1=top[x],f2=top[y];
while (f1^f2){
if (h[f1]<h[f2]) swap(f1,f2),swap(x,y);
g[dfn[f1]].push_back(z);
g[dfn[x]+1].push_back(-z);
x=fa[top[x]],f1=top[x];}
if (h[x]>h[y]) swap(x,y);
g[dfn[x]].push_back(z);
g[dfn[y]+1].push_back(-z);}
fo(i,1,n){
for(j=0;j<g[i].size();j++){
x=g[i][j];
y=x>0?1:-1;
change(1,1,tot,abs(x),y);}
edge t=find(1,1,tot,1,tot);
ans[seq[i]]=pre[t.y];
}
fo(i,1,n) printf("%d\n",ans[i]);
}