テール6302雨の0x60「グラフ理論」の例
背景
えりは深い憎しみの雨となっています。
暑い夏の前半に浸透し、その後、大雨とその結果としての洪水は、すべてを消滅。
深いえりの家が洪水頑固な抵抗の小さな村を持っていますが、またいくつかの古い家屋が倒壊が、木は木を根こそぎにし、穀物のフィールドが混乱して混乱しています。
えり深い不満や村人が存続するために救援食糧を待たなければなりませんでした。
しかし、リリーフ食品は非常に特別な方法が配布されています。
説明
N(N≤10^ 5)ツリー構造を形成する点があります。
M(M≤10^ 5)の動作時間を発行、発行バッグZ((X、Yを含む)をXからYへの経路上の各点のための2つの点X、Yを選択するたびにz≤10^ 9でありますアイテムの)タイプ。
すべての必要な決済業務が完了した後、アイテムの種類に各ポイントストアまで。
入力形式
2つの正の整数N、M、図に示すように、被験者の意味の最初の行。
次に、2つの数のN-1ラインが(a、b)は、(B)の間にエッジがあることを示します。
3つの数字(x、y、z)は、図に示すように、被験者の意味の次のm行。
出力フォーマット
最小出力番号のようなレリーフ食品貯蔵時間の様々な、存在する場合、リリーフ食品貯蔵の第I種最大の家を表すn行、第i列整数、。
救援食糧何家が存在しない場合は、出力の行が0に対応しています。
サンプル入力
5 3 1 2 3 1 2 3 4 5 3 2 3 3 1 5 2 3 3 3
サンプル出力
2 3 3 0 2
データ範囲と表記
- データの20%を、1 <= N、M <= 100
- データの50%、1 <= N、M <= 2000
- データを、1 <= N、M <= 100000、1 <=、B、X、Y <= N、1 <= Z <= 100000の100%に
ソース
Vani、Vaniが任命カップトーナメントを持っています
問題の解決策
ツリーはLCAで、FAは[LCA]cm⁻¹するために、微分計数記事、xの各物品のY + 1のために使用することができます。
問題を解決するために宇宙セグメントツリーのマージを使用してください。時間複雑\(O(N \ログN )\)
tarjanシークLCAを実施するために。
#include<bits/stdc++.h>
#define rg register
#define il inline
#define co const
template<class T>il T read(){
rg T data=0,w=1;rg char ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-') w=-w;
for(;isdigit(ch);ch=getchar()) data=data*10+ch-'0';
return data*w;
}
template<class T>il T read(rg T&x) {return x=read<T>();}
typedef long long ll;
using namespace std;
co int N=1e5+1;
int n,m;
// tarjan lca
vector<int> e[N];
int x[N],y[N],z[N],val[N],cnt;
vector<pair<int,int> > q[N];
int vis[N],pa[N],lca[N],fa[N]; // pa for disjoint set,fa for real father
int find(int x) {return pa[x]==x?x:pa[x]=find(pa[x]);}
void tarjan(int x){
vis[x]=1;
for(int i=0,y;i<e[x].size();++i){
if(vis[y=e[x][i]]) continue;
tarjan(y);
pa[y]=fa[y]=x;
}
for(int i=0,y;i<q[x].size();++i)
if(vis[y=q[x][i].first]==2)
lca[q[x][i].second]=find(y);
vis[x]=2;
}
// Interval Tree
int tot,lc[N*72],rc[N*72],dat[N*72],pos[N*72];
void insert(int&x,int l,int r,int p,int d){
if(!x) x=++tot;
if(l==r){
dat[x]+=d,pos[x]=dat[x]?l:0;
return;
}
int mid=l+r>>1;
if(p<=mid) insert(lc[x],l,mid,p,d);
else insert(rc[x],mid+1,r,p,d);
if(dat[lc[x]]>=dat[rc[x]])
dat[x]=dat[lc[x]],pos[x]=pos[lc[x]];
else
dat[x]=dat[rc[x]],pos[x]=pos[rc[x]];
}
int merge(int x,int y,int l,int r){
if(!x||!y) return x+y;
if(l==r){
dat[x]+=dat[y],pos[x]=dat[x]?l:0;
return x;
}
int mid=l+r>>1; // edit 1: >>
lc[x]=merge(lc[x],lc[y],l,mid);
rc[x]=merge(rc[x],rc[y],mid+1,r);
if(dat[lc[x]]>=dat[rc[x]])
dat[x]=dat[lc[x]],pos[x]=pos[lc[x]];
else
dat[x]=dat[rc[x]],pos[x]=pos[rc[x]];
return x;
}
int root[N],ans[N];
void dfs(int x){
for(int i=0,y;i<e[x].size();++i){
if((y=e[x][i])==fa[x]) continue;
dfs(y);
root[x]=merge(root[x],root[y],1,cnt);
}
ans[x]=pos[root[x]];
}
int main(){
// freopen("CH6302.in","r",stdin),freopen("CH6302.out","w",stdout);
read(n),read(m);
for(int i=1,x,y;i<n;++i){
read(x),read(y);
e[x].push_back(y),e[y].push_back(x);
}
for(int i=1;i<=m;++i){
read(x[i]),read(y[i]),val[i]=read(z[i]);
if(x[i]==y[i]) lca[i]=x[i];
else q[x[i]].push_back(make_pair(y[i],i)),q[y[i]].push_back(make_pair(x[i],i));
}
for(int i=1;i<=n;++i) pa[i]=i;
tarjan(1);
sort(val+1,val+m+1),cnt=unique(val+1,val+m+1)-val-1;
for(int i=1;i<=m;++i){
z[i]=lower_bound(val+1,val+cnt+1,z[i])-val;
// cerr<<i<<" lca="<<lca[i]<<endl;
insert(root[x[i]],1,cnt,z[i],1);
insert(root[y[i]],1,cnt,z[i],1);
insert(root[lca[i]],1,cnt,z[i],-1);
if(fa[lca[i]]) insert(root[fa[lca[i]]],1,cnt,z[i],-1);
}
dfs(1);
for(int i=1;i<=n;++i) printf("%d\n",val[ans[i]]);
return 0;
}