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]);
}