bzoj 3307 雨天的尾巴 線段樹

2021-08-07 07:52:46 字數 1675 閱讀 3156

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

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

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

1<=n,m<=100000

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

1<=z<=10^9

比較巧妙的一道題。

考慮如果是在一條鏈上的話要怎麼做。那麼我們可以在x處加乙個加入z的標記,在y+1出加入乙個刪掉z的標記,然後用權值線段樹掃一遍就好了。

現在拓展到一棵樹上,我們可以在x和y處加入乙個加上z的標記,在lca和fa[lca]處加入乙個刪除z的標記,那麼我們每次可以把子節點的線段樹合併上來,然後處理標記資訊,最後查詢答案即可。

#include

#include

#include

#include

#include

using namespace std;

const int n=100005;

const int inf=1000000000;

int n,m,last[n],ls[n],fa[n][20],dep[n],cnt,sz,root[n],ans[n];

struct edgee[n*6];

struct treet[n*40];

intread()

while (ch>='0'&&ch<='9')

return

x*f;

}void addedge(int u,int v)

void dfs(intx)}

int get_lca(int

x,int

y)void ins(int &d,int l,int r,int

x,int

y) int mid=(l+r)/2;

if (x

<=mid) ins(t[d].l,l,mid,x,y);

else ins(t[d].r,mid+1,r,x,y);

t[d].mx=max(t[t[d].l].mx,t[t[d].r].mx);

}int merge(int d,int p,int l,int r)

int mid=(l+r)/2;

t[d].l=merge(t[d].l,t[p].l,l,mid);

t[d].r=merge(t[d].r,t[p].r,mid+1,r);

t[d].mx=max(t[t[d].l].mx,t[t[d].r].mx);

return d;

}int query(int d,int l,int r)

void solve(int

x) for (int i=ls[x];i;i=e[i].next)

if (e[i].to>0) ins(root[x],0,inf,e[i].to,1);

else ins(root[x],0,inf,-e[i].to,-1);

ans[x]=query(root[x],0,inf);

}int main()

dfs(1);

for (int i=1;i<=m;i++)

solve(1);

for (int i=1;i<=n;i++) printf("%d\n",ans[i]);

return

0;}

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...

BZOJ3307 雨天的尾巴

bzoj許可權題 良心洛谷 這道題目的花呢,本來想縮先樹剖 可能需要長鏈剖分?再搞乙個標記永久化,然後最後合併答案,不過可能會卡空間。時間複雜度呢是o nlog 2n o n log2 n 然後boshi表示 為什麼不差分然後再自底向上合併線段樹呢 於是就做到了o nlog n o n logn 好...