HDU5221 Occupation 樹鏈剖分

2022-08-22 04:18:09 字數 2342 閱讀 8711

題意:

給出一棵樹,root=1,樹有點權,有乙個人叫做m

有3種操作:

1 u v 把u到v路徑上的所有點的點權都給m

2 u 若u的點權在m手上,拿走

3 u 把u為根的子樹的所有點權都給m

每乙個操作過後,輸出m擁有的點權

想法:要維護路徑,用樹鏈剖分

要維護子樹,用dfs序

但是這樣貌似要寫很多

然而後來知道

樹鏈剖分是有dfs序的,也就是說,樹鏈剖分後,對於乙個點,其子樹所有點的新編號剛好在該點新編號後面的乙個連續的區間裡面,這個區間的範圍[chg[u],chg[u]+siz[u]-1],

這樣的話就方便了,我們只需要乙個樹鏈剖分就可以了。

樹鏈剖分後用線段樹維護,

線段樹維護3個值:

all:若區間都被m擁有了,all為1,否則為0

val:在該區間內,m擁有的所有點權的和

sum:在該區間內,所有點的點權的和

(sum在build後就是固定的,不需要再更改)

我們只需要update2個:all和val

這樣每一次update後,答案就是seg[1].val了

其實剛開始的時候我只維護2個值:all和sum

然後每一次update操作後我就query一次求出val,然而這樣肯定超時啊

加了個val後query函式就直接省略了

#pragma comment(linker, "/stack:102400000,102400000")#include

#include

#include

#include

#define lson l,m,rt<<1

#define rson m+1,r,rt<<1|1

using

namespace

std;

const

int maxn=1e5+10

;const

int inf=0x3f3f3f3f

;struct

seg;

seg seg[maxn

<<2

];int

a[maxn];

intdep[maxn];

intsiz[maxn];

intson[maxn];

intfa[maxn];

inttop[maxn];

intchg[maxn];

intrev[maxn];

struct

edge

;edge edge[maxn

<<1

];int

head[maxn];

inttot;

void

init()

void addedge(int u,int

v)void solve(int

);int

main()

for(int i=1;i)

solve(n);

}return0;

}void dfs0(int u,int

pre)

}void dfs1(int u,int

tp)}

void pushup(int

rt)void build(int l,int r,int

rt)

int m=(l+r)>>1

; build(lson);

build(rson);

seg[rt].sum=seg[rt<<1].sum+seg[rt<<1|1

].sum;

}void pushdown(int

rt)}

void update_seg(int l,int r,int add,int l,int r,int

rt)

int m=(l+r)>>1

; pushdown(rt);

if(l<=m)

update_seg(l,r,add,lson);

if(r>m)

update_seg(l,r,add,rson);

pushup(rt);

}void update_path(int u,int

v)

if(dep[u]swap(u,v);

update_seg(chg[v],chg[u],

1,1,tot,1);}

void solve(int

n)

else

else

}printf(

"%d\n

",seg[1

].val);

}return

;}

樹鏈剖分 hdu5221 Occupation

給定一棵樹,每個結點上有乙個權值,然後給q個操作,每個操作為 1.占領這個樹上兩個結點路徑上的所有結點,包括起點和終點 2.取消某個結點的占領 3.占領以某個結點為根的整棵子樹 對於每個操作,返回完成這個操作後整棵樹被占領結點的權值之和 在操作線段樹時,區間更新需要打懶標記,不然會超時 includ...

Occupation hdu5221 樹鏈剖分

題意 一開始有n個點 且每個點有其價值 有三個操作 1 選取路徑 x y 並獲得其價值 2 刪除x的價值 也就是放棄x 如果x未選擇就不用刪除 3 選取x及x的子樹 每次詢問都要輸出獲得的價值總和 三個操作都很簡單 主要是是線段樹有一點不一樣 用字首和可以解決 見 includeusing name...

HDU3966 樹鏈剖分

題目 aragorn s story 題意 給一棵樹,並給定各個點權的值,然後有3種操作 i c1 c2 k 把c1與c2的路徑上的所有點權值加上k d c1 c2 k 把c1與c2的路徑上的所有點權值減去k q c 查詢節點編號為c的權值 分析 典型的樹鏈剖分題目,先進行剖分,然後用線段樹去維護即...