\(n\) 個點,形成乙個樹狀結構。有 \(m\) 次發放,每次選擇兩個點 \(x,y\) 對於 \(x\) 到 \(y\) 的路徑上(含 \(x,y\))每個點發一袋 \(z\) 型別的物品。完成所有發放後,每個點存放最多的是哪種物品。
第一行數字 \(n,m\)
接下來 \(n-1\) 行,每行兩個數字 \(a,b\),表示 \(a\) 與 \(b\) 間有一條邊
再接下來 \(m\) 行,每行三個數字 \(x,y,z\).如題
輸出有 \(n\) 行
每 \(i\) 行的數字表示第 \(i\) 個點存放最多的物品是哪一種,如果有多種物品的數量一樣,輸出編號最小的。如果某個點沒有物品則輸出 \(0\)
板子題詳見**
#include#include#include#include#define n 100005
#define m 6000005
#define r register
using namespace std;
inline int read()
while(ch>='0'&&ch<='9')
return x*f;
}int n,m,ed,head[n],siz[n],dep[n],f[n],son[n],top[n];
int tr[m],mx[m],ls[m],rs[m];//tr記錄的是線段樹中每個物品的種類數,mx記錄的是種類數最多的物品
int ans[n],cnt,x[n],y[n],z[n],rt[n]; //rt表示每個結點的線段樹的根節點
struct edgee[n<<1];
int len;
void addedge(int u,int v)
void dfs1(int u,int fa)
}void dfs2(int u,int tp)
}int lca(int x,int y)
int modify(int rt,int l,int r,int pos,int val)
int mid = (l+r)>>1;
if(pos<=mid)ls[rt] = modify(ls[rt],l,mid,pos,val);
else rs[rt] = modify(rs[rt],mid+1,r,pos,val);
pushup(rt);
return rt;
}int merge(int a,int b,int l,int r)
int mid = (l+r)>>1;
ls[a] = merge(ls[a],ls[b],l,mid),rs[a] = merge(rs[a],rs[b],mid+1,r);
pushup(a);
return a;
}void get_ans(int u)
} if(tr[rt[u]])ans[u] = mx[rt[u]];
}int main()
dfs1(1,0),dfs2(1,1);//注意是dfs1(1,0)而不是dfs1(1,1),因為這個坑花了多長時間就不提了:-)
for(r int i = 1;i <= m;i++)
for(r int i=1;i<=m;i++)
get_ans(1);
for(r int i = 1;i <= n;i++)printf("%d\n",ans[i]);
return 0;
}
P4556 雨天的尾巴 樹上差分, 樹鏈剖分
鏈結 給出一棵n n個結點的樹,有mm 次修改操作,每次操作要求將a,b a,b之間最短路徑所有點加上型別為c c的糧食11次,到最後輸出每個點所儲存的最多的糧食型別,如果有相等數量的,則輸出型別編號最小的.n,m c 1 05n,m,c 1 05整體使用 set set 維護,會發現由於左兒子對右...
bzoj3307 雨天的尾巴 線段樹合併
description n個點,形成乙個樹狀結構。有m次發放,每次選擇兩個點x,y 對於x到y的路徑上 含x,y 每個點發一袋z型別的物品。完成 所有發放後,每個點存放最多的是哪種物品。input 第一行數字n,m 接下來n 1行,每行兩個數字a,b,表示a與b間有一條邊 再接下來m行,每行三個數字...
bzoj3307 雨天的尾巴 線段樹合併
n個點,形成乙個樹狀結構。有m次發放,每次選擇兩個點x,y 對於x到y的路徑上 含x,y 每個點發一袋z型別的物品。完成 所有發放後,每個點存放最多的是哪種物品。1 n,m 100000 1 a,b,x,y n 1 z 10 9 乙個非常直觀的方法就是輕重鏈剖分然後樹狀陣列套權值線段樹,這樣非常無腦...