雨天的尾巴 線段樹合併 樹上差分

2022-03-19 18:55:37 字數 1713 閱讀 5271

\(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 乙個非常直觀的方法就是輕重鏈剖分然後樹狀陣列套權值線段樹,這樣非常無腦...