jzoj5463 【NOIP2017提高A組衝刺11.8】證書

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]);
}
發佈了58 篇原創文章 · 獲贊 1 · 訪問量 6151
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章