题目链接:
https://www.acwing.com/problem/content/submission/code_detail/191343/
思路:
如果物品类型只有一种直接差分,但是物品有多种,而且还要求最值,便在每个节点开一个线段树(最开始仅仅维护差分数组,为节省空间,只能动态开点)。
执行树上差分,最后线段树合并,即可求出每个节点最值。还要注意线段树维护的区间太大会超时,需要离散化。
ps:看了思路也调了n久
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=100000+5; 4 int INF; 5 int n,m; 6 7 int head[N],ver[2*N],nex[2*N],tot=0; 8 9 inline void add(int x,int y) 10 { 11 ver[++tot]=y; 12 nex[tot]=head[x]; 13 head[x]=tot; 14 } 15 16 int d[N],f[N][20],t; 17 void bfs() 18 { 19 t=log(n)/log(2)+1; 20 d[1]=1; 21 queue<int> q; 22 q.push(1); 23 while(!q.empty()) 24 { 25 int x=q.front(); 26 q.pop(); 27 for(int i=head[x];i;i=nex[i]) 28 { 29 int y=ver[i]; 30 if(d[y]) 31 continue; 32 d[y]=d[x]+1; 33 f[y][0]=x; 34 for(int i=1;i<=t;++i) 35 f[y][i]=f[f[y][i-1]][i-1]; 36 q.push(y); 37 } 38 } 39 } 40 41 int lca(int x,int y) 42 { 43 if(d[x]<d[y])swap(x,y); 44 if(d[x]>d[y]) 45 for(int i=t;i>=0;--i) 46 if(d[f[x][i]]>=d[y])x=f[x][i]; 47 if(x==y) 48 return x; 49 for(int i=t;i>=0;--i) 50 if(f[x][i]!=f[y][i]) 51 x=f[x][i],y=f[y][i]; 52 return f[x][0]; 53 } 54 55 struct SegmentTree 56 { 57 int dat,id,lc,rc; 58 }; 59 60 SegmentTree tree[4*N*16]; 61 int tot2=0; 62 63 void pushup(int p) 64 { 65 if(tree[tree[p].lc].dat>=tree[tree[p].rc].dat) 66 { 67 tree[p].dat=tree[tree[p].lc].dat; 68 tree[p].id=tree[tree[p].lc].id; 69 } 70 else 71 { 72 tree[p].dat=tree[tree[p].rc].dat; 73 tree[p].id=tree[tree[p].rc].id; 74 } 75 } 76 77 void change(int pos,int v,int p,int l,int r) 78 { 79 if(r-l==1) 80 { 81 tree[p].dat+=v; 82 tree[p].id=pos; 83 return; 84 } 85 int m=(l+r)>>1; 86 if(pos<m) 87 { 88 if(!tree[p].lc)tree[p].lc=++tot2; 89 change(pos,v,tree[p].lc,l,m); 90 } 91 else 92 { 93 if(!tree[p].rc)tree[p].rc=++tot2; 94 change(pos,v,tree[p].rc,m,r); 95 } 96 pushup(p); 97 } 98 99 int merge(int p,int q,int l,int r) 100 { 101 if(!p)return q; 102 if(!q)return p; 103 if(r-l==1) 104 { 105 tree[p].dat+=tree[q].dat; 106 return p; 107 } 108 109 int m=(l+r)>>1; 110 111 tree[p].lc=merge(tree[p].lc,tree[q].lc,l,m); 112 tree[p].rc=merge(tree[p].rc,tree[q].rc,m,r); 113 114 pushup(p); 115 return p; 116 } 117 118 int ans[N],vis[N]; 119 120 void dfs(int x) 121 { 122 vis[x]=1; 123 for(int i=head[x];i;i=nex[i]) 124 { 125 int y=ver[i]; 126 if(vis[y]) 127 continue; 128 dfs(y); 129 merge(x,y,0,INF); 130 } 131 ans[x]=tree[x].id; 132 } 133 134 int xx[N],yy[N],zz[N]; 135 int disc[N],tot3; 136 137 int main() 138 { 139 scanf("%d%d",&n,&m); 140 141 for(int i=1;i<n;++i) 142 { 143 int x,y; 144 scanf("%d%d",&x,&y); 145 add(x,y); 146 add(y,x); 147 } 148 bfs(); 149 tot2=n; 150 151 for(int i=0;i<m;++i) 152 { 153 scanf("%d%d%d",xx+i,yy+i,zz+i); 154 disc[++tot3]=zz[i]; 155 } 156 ++tot3; 157 sort(disc,disc+tot3); 158 INF=unique(disc,disc+tot3)-disc; 159 160 for(int i=0;i<m;++i) 161 { 162 int x,y,z; 163 x=xx[i]; 164 y=yy[i]; 165 z=lower_bound(disc,disc+INF,zz[i])-disc; 166 int anc=lca(x,y); 167 change(z,1,x,0,INF); 168 change(z,1,y,0,INF); 169 change(z,-1,anc,0,INF); 170 if(anc!=1) 171 change(z,-1,f[anc][0],0,INF); 172 } 173 174 dfs(1); 175 for(int i=1;i<=n;++i) 176 printf("%d\n",disc[ans[i]]); 177 178 return 0; 179 }