樹鏈剖分 月下毛景樹

2022-05-27 00:57:07 字數 3144 閱讀 7173

毛毛蟲經過及時的變形,最終逃過的一劫,離開了菜媽的菜園。 毛毛蟲經過千山萬水,歷盡千辛萬苦,最後來到了小小的紹興一中的校園裡。

爬啊爬毛毛蟲爬到了一顆小小的「毛景樹」下面,發現樹上長著他最愛吃的毛毛果~ 「毛景樹」上有n個節點和n-1條樹枝,但節點上是沒有毛毛果的,毛毛果都是長在樹枝上的。但是這棵「毛景樹」有著神奇的魔力,他能改變樹枝上毛毛果的個數:

輸入格式:

第一行乙個正整數n。

接下來n-1行,每行三個正整數ui,vi和wi,第i+1行描述第i條樹枝。表示第i條樹枝連線節點ui和節點vi,樹枝上有wi個毛毛果。 接下來是操作和詢問,以「stop」結束。

輸出格式:

對於毛毛蟲的每個詢問操作,輸出乙個答案。

三個小時做這一道題,卻是因為乙個變數名寫錯。

好吧,還是要總結的,不然也沒有收穫不是?

這是一道比較簡單的樹剖,可以說是裸題。

但也有以下幾個問題需要注意。

1,題目中給出的是邊權,那麼考慮怎樣才會計算到邊權,因為每個點只有乙個父親,所以可以想到把每條邊的邊權轉移到深度較大的點上,這也是一種邊權轉點權的常見套路,需要記住。

2,題目要求我們維護區間最大值,區間加和區間覆蓋。

對於線段樹的兩種操作(推廣到多個操作),一定要考慮操作的優先順序。

一般的算術操作要推式子,這道題的區間覆蓋顯然不用推式子。

那麼考慮如果當前線段樹內的該節點有乙個區間加的tag,那麼當我們執行區間覆蓋時,就一定要把區間加標記去掉,因為不可以讓這段區間在區間覆蓋之後再次因為之前的區間加標記改變,想一想其實很容易理解。

3,針對這道題的幾個操作,我們發現在樹剖的時候,因為我們每個點的點權其實是點向上的邊的邊權,所以就會發現,對於每次操作的x,y兩點,他們的lca是一定不能參與到任何操作或者計算的,因為lca的對應的邊並不在x到y的區間內,所以每次操作之前把lca特殊處理一下,再在操作之後將lca的資料維護一下即可。比較簡單。

code:

#include#include#define ls(o) o<<1

#define rs(o) o<<1|1

#define int long long

using namespace std;

const int wx=100017;

inline int read()

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

return sum*f;

}struct val_treet[wx*4];

struct eedge[wx*2];

char opt[9];

int num,tot,n,x,y,z,k;

int head[wx],f[wx][23];

int a[wx],tid[wx],dfn[wx],dep[wx],size[wx],son[wx],top[wx],fa[wx];

void swap(int &x,int &y)

void add(int from,int to,int dis)

void up(int o)

void down(int o)

if(tag(o))

ta(o)=-1;

tag(o)=0;

}void build(int o,int l,int r)

int mid=t[o].l+t[o].r>>1;

build(ls(o),l,mid);

build(rs(o),mid+1,r);

up(o);

}void update_add(int o,int l,int r,int k)

down(o);

int mid=t[o].l+t[o].r>>1;

if(l<=mid)update_add(ls(o),l,r,k);

if(r>mid)update_add(rs(o),l,r,k);

up(o);

}void update_change(int o,int l,int r,int k)

down(o);

int mid=t[o].l+t[o].r>>1;

if(l<=mid)update_change(ls(o),l,r,k);

if(r>mid)update_change(rs(o),l,r,k);

up(o);

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

down(o);

int maxn=-1;

int mid=t[o].l+t[o].r>>1;

if(l<=mid)maxn=max(maxn,query(ls(o),l,r));

if(r>mid)maxn=max(maxn,query(rs(o),l,r));

return maxn;

}void dfs_a(int u,int father) }}

void dfs_b(int u,int topf)

}int c_query(int x,int y)

if(dfn[x]>dfn[y])swap(x,y);

maxn=max(maxn,query(1,dfn[x],dfn[y]));

return maxn;

}void c_update_add(int x,int y,int k)

if(dfn[x]>dfn[y])swap(x,y);

update_add(1,dfn[x],dfn[y],k);

}void c_update_change(int x,int y,int k)

if(dfn[x]>dfn[y])swap(x,y);

update_change(1,dfn[x],dfn[y],k);

}void pre()

int lca(int x,int y)

if(x==y)return x;

for(int i=21;i>=0;i--)

return f[x][0];

}signed main()

else update_change(1,dfn[edge[x*2-1].to],dfn[edge[x*2-1].to],y);

} else if(opt[2]=='o')

else if(opt[1]=='a')

else

} return 0;

}

月下「毛景樹」

bzoj1984 搞了我好久好久好久好久才ac的。差不多昨天4小時 今天的2小時。這題還是差點破300行。由於我不會樹鏈剖分,所以就用了link cut tree。鑑於link cut tree的常數實在太大了,榮幸的成為ac程式中速度最慢的。總耗時7777ms。這題麻煩的就是標記傳遞 由於link...

bzoj1984 月下「毛景樹」 樹鏈剖分

time limit 20 sec memory limit 64 mb submit status discuss 毛毛蟲經過及時的變形,最終逃過的一劫,離開了菜媽的菜園。毛毛蟲經過千山萬水,歷盡千辛萬苦,最後來到了小小的紹興一中的校園裡。爬啊爬 爬啊爬 毛毛蟲爬到了一顆小小的 毛景樹 下面,發現...

P4315 月下「毛景樹」(樹鏈剖分)

毛毛蟲經過及時的變形,最終逃過的一劫,離開了菜媽的菜園。毛毛蟲經過千山萬水,歷盡千辛萬苦,最後來到了小小的紹興一中的校園裡。爬啊爬 爬啊爬毛毛蟲爬到了一顆小小的 毛景樹 下面,發現樹上長著他最愛吃的毛毛果 毛景樹 上有n個節點和n 1條樹枝,但節點上是沒有毛毛果的,毛毛果都是長在樹枝上的。但是這棵 ...