bzoj3307 雨天的尾巴 線段樹合併

2021-08-20 17:48:26 字數 1801 閱讀 6194

n個點,形成乙個樹狀結構。有m次發放,每次選擇兩個點x,y

對於x到y的路徑上(含x,y)每個點發一袋z型別的物品。完成

所有發放後,每個點存放最多的是哪種物品。

1<=n,m<=100000

1<=a,b,x,y<=n

1<=z<=10^9

乙個非常直觀的方法就是輕重鏈剖分然後樹狀陣列套權值線段樹,這樣非常無腦而且好寫

另乙個也比較直觀的方法就是對於乙個操作(x,y,z)在lca和fa[lca]處打標記,在x和y處打標記,然後遍歷樹的時候每個節點分別繼承所有兒子的線段樹的並即可,這樣也非常無腦

第一次打線段樹合併,紀念一下

#include 

#include

#include

#include

#define rep(i,st,ed) for (int i=st;i<=ed;++i)

#define drp(i,st,ed) for (int i=st;i>=ed;--i)

const

int lim=1000000000;

const

int n=100005;

struct edge e[n*2];

struct treenode t[n*34];

std:: vector

tag[n];

int dep[n],fa[n][19],root[n];

int ans[n],ls[n],edcnt,n,t,tot;

int read()

void add_edge(int x,int y) ; ls[x]=edcnt;

e[++edcnt]=(edge) ; ls[y]=edcnt;

}void modify(int &now,int tl,int tr,int x,int v) ;

if (tl==tr)

int mid=(tl+tr)>>1;

if (x<=mid) modify(t[now].l,tl,mid,x,v);

else modify(t[now].r,mid+1,tr,x,v);

t[now].max=std:: max(t[t[now].l].max,t[t[now].r].max);

}int merge(int x,int y,int tl,int tr)

int mid=(tl+tr)>>1;

t[x].l=merge(t[x].l,t[y].l,tl,mid);

t[x].r=merge(t[x].r,t[y].r,mid+1,tr);

t[x].max=std:: max(t[t[x].l].max,t[t[x].r].max);

return x;

}int get_lca(int x,int y)

void dfs(int now)

}int query(int now,int tl,int tr)

void solve(int now)

for (int i=0;iif (tag[now][i]>0) modify(root[now],0,lim,tag[now][i],1);

if (tag[now][i]<0) modify(root[now],0,lim,-tag[now][i],-1);

}ans[now]=query(root[now],0,lim);

}int main(void)

solve(1);

rep(i,1,n) printf("%d\n", ans[i]);

return

0;}

bzoj 3307 雨天的尾巴 線段樹

n個點,形成乙個樹狀結構。有m次發放,每次選擇兩個點x,y 對於x到y的路徑上 含x,y 每個點發一袋z型別的物品。完成 所有發放後,每個點存放最多的是哪種物品。1 n,m 100000 1 a,b,x,y n 1 z 10 9 比較巧妙的一道題。考慮如果是在一條鏈上的話要怎麼做。那麼我們可以在x處...

bzoj3307 雨天的尾巴

time limit 10 sec memory limit 128 mb submit 258 solved 121 submit status discuss n個點,形成乙個樹狀結構。有m次發放,每次選擇兩個點x,y 對於x到y的路徑上 含x,y 每個點發一袋z型別的物品。完成 所有發放後,每...

BZOJ3307 雨天的尾巴

線段樹合併 在鏈的兩端x,y各打上1個z的加標記,在lca x,y 打上1個z的減標記,在fa lca x,y 打上1個z的減標記,每個節點和所有孩子的線段樹合併,查詢時線段樹上二分 code include include include include include include inclu...