給出一棵n個點的樹,有m個操做
php
每一個操做輸入x,y,z,表示x到y的路徑上的全部點都放一個編號爲z的物品node
最後輸出每一個點存放最多的物品是哪一個(若是有存放數量相同的物品,輸出編號小的)spa
對於每種操做至關於區間增值,那就樹上差分,而由於物品不一樣,因此每一個點都用主席樹來維護
code
主席樹上的葉子節點爲物品,點權爲出現的數量blog
而後求答案的時候從葉子節點向上合併主席樹就好了,由於合併以後的主席樹的葉子節點的點權確定都是>=0get
因此在合併以後再更新最大值就好了string
PS:這題有點小卡空間it
#include<cstdio> #include<cstdlib> #include<cmath> #include<algorithm> #include<cstring> #define Maxn 110000 using namespace std; struct node{int x,y,next;}a[Maxn*2];int len,last[Maxn]; void ins(int x,int y){a[++len]=(node){x,y,last[x]};last[x]=len;} int f[Maxn][21],dep[Maxn]; void dfs(int x) { for(int i=1;dep[x]>=(1<<i);i++) { f[x][i]=f[f[x][i-1]][i-1]; } for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(y==f[x][0]) continue; f[y][0]=x; dep[y]=dep[x]+1; dfs(y); } } int LCA(int x,int y) { if(dep[x]<dep[y]) swap(x,y); for(int i=20;i>=0;i--) { if(dep[x]-dep[y]>=(1<<i)) x=f[x][i]; } if(x==y) return x; for(int i=20;i>=0;i--) { if(dep[x]>=(1<<i)&&f[x][i]!=f[y][i]) { x=f[x][i];y=f[y][i]; } } return f[x][0]; } struct trnode{int lc,rc,mx;}tr[Maxn*60];int rt[Maxn],tot; void update(int u) { int lc=tr[u].lc,rc=tr[u].rc; if(lc!=0&&rc!=0) { if(tr[lc].mx>=tr[rc].mx) tr[u].mx=tr[lc].mx; else tr[u].mx=tr[rc].mx; } else if(lc!=0) tr[u].mx=tr[lc].mx; else if(rc!=0) tr[u].mx=tr[rc].mx; } void add(int &u,int x,int d,int l,int r) { if(u==0) u=++tot; if(l==r) { tr[u].mx+=d; return ; } int mid=(l+r)/2; if(x<=mid) add(tr[u].lc,x,d,l,mid); else add(tr[u].rc,x,d,mid+1,r); update(u); } void Merge(int &u1,int u2,int l,int r) { if(u1==0){u1=u2;return ;} if(u2==0) return ; if(l==r) { tr[u1].mx+=tr[u2].mx; return ; } int mid=(l+r)/2; Merge(tr[u1].lc,tr[u2].lc,l,mid); Merge(tr[u1].rc,tr[u2].rc,mid+1,r); update(u1); } struct query{int x,y,p,z;}Q[Maxn];int to[Maxn],p; bool cmp(query n1,query n2){return n1.z<n2.z;} int ans[Maxn]; int gett(int u,int l,int r) { if(l==r) return l; int lc=tr[u].lc,rc=tr[u].rc,mid=(l+r)/2; if(tr[lc].mx>=tr[rc].mx) return gett(lc,l,mid); else return gett(rc,mid+1,r); } void solve(int x) { for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(y==f[x][0]) continue; solve(y); Merge(rt[x],rt[y],1,p); } if(tr[rt[x]].mx<=0) ans[x]=0; else ans[x]=to[gett(rt[x],1,p)]; } int main() { int n,m; scanf("%d%d",&n,&m); len=0;memset(last,0,sizeof(last)); for(int i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); ins(x,y);ins(y,x); } dep[1]=1;f[1][0]=0;dfs(1); memset(rt,0,sizeof(rt));tot=0; for(int i=1;i<=m;i++) scanf("%d%d%d",&Q[i].x,&Q[i].y,&Q[i].z); sort(Q+1,Q+m+1,cmp); p=1;Q[1].p=p;to[1]=Q[1].z; for(int i=2;i<=m;i++) { if(Q[i].z!=Q[i-1].z) p++; Q[i].p=p;to[p]=Q[i].z; } for(int i=1;i<=m;i++) { int x=Q[i].x,y=Q[i].y,z=Q[i].p; int lca=LCA(x,y); add(rt[x],z,1,1,p);add(rt[y],z,1,1,p);add(rt[lca],z,-1,1,p); if(f[lca][0]!=0) add(rt[f[lca][0]],z,-1,1,p); } solve(1); for(int i=1;i<=n;i++) printf("%d\n",ans[i]); return 0; }