HDU 5029 樹鏈剖分 權值線段樹

2021-08-19 18:34:47 字數 3040 閱讀 2073

題目鏈結

題意:給定一顆n個結點的樹,進行m次染色操作,對於每一次染色操作是選擇樹上的一條路徑,將路徑上所有節點都染上第z

zz種顏色。

輸出m次操作以後,每乙個節點上染色次數最多的顏色。

1

<=n

,m,z

<=1

e5

1<=n,m,z <= 1e5

1<=n

,m,z

<=1

e5思路:

對於樹上的路徑操作,自然能夠想到使用樹鏈剖分,將樹形結構轉化為線形結構,並能夠將樹上的路徑劃分為幾個連續的區間。

隨後問題轉化為:

在乙個一維數軸上,進行m次染色,每次選擇乙個區間染成某一種顏色,問最後每乙個點染色次數最多的顏色。

對於該問題,我們首先考慮乙個簡單的版本,即只存在一種顏色,我們如何求出該顏色在每乙個點的染色次數呢?

考慮掃瞄線,即對於每乙個區間[l,

r]

[l,r]

[l,r

],我們在l

ll處加1,r+1

r+1r+

1處減1

11,最後掃一遍即可。

那對於多種顏色,雖然計算還是+1或者-1的計算,但為了區分不同的顏色,對於顏色k

kk,我們標記時使用+k+k

+k或− k-k

−k。此時對於該題我們就有了清晰的思路,首先對於每乙個點開乙個vector,用於儲存該點的標記。

隨後對於每一次染色,使用樹鏈剖分將路徑轉化為幾個連續的區間,對於區間[l,

r]

[l,r]

[l,r

]染第k

kk種顏色,我們就更新:

vector<

int> vec[n+1]

;for x in all_segment:

vec[x.l]

.push_back

(x.k)

; vec[x.r]

.push_back

(-x.k)

;

定義陣列:ans[i]:第i種節點當前的染色次數

按順序遍歷節點,隨後遍歷其對應的vector,更新ans陣列。

隨後從ans陣列裡面找出值最大且序號最小的下標即可。

這一步可以使用權值線段樹進行優化。

此題得解。

**:

#include

#include

#include

#include

#include

using

namespace std;

typedef

long

long ll;

#define lson rt<<1

#define rson rt<<1|1

const

int a =

1e5+10;

class

grag[a<<2]

;class

seg_tree

tree[a<<2]

;int n,m,head[a]

,tot,twt;

int fa[a]

,dep[a]

,siz[a]

,son[a]

,top[a]

,pos[a]

,id[a]

,ans[a]

;vector<

int> v[a]

;void

init()

siz[0]

=0; tot = twt =0;

}void

add(

int u,

int v)

void

dfs(

int u,

int pre,

int d)

}void

dfs(

int u,

int tp)

}void

calc

(int x,

int y,

int c)

if(dep[x]

> dep[y]

)swap

(x,y)

; v[pos[x]].

push_back

(c);

v[pos[y]+1

].push_back

(-c);}

void

push_up

(int rt)

void

build_tree

(int rt,

int l,

int r)

void

update

(int rt,

int pos,

int c)

int mid =

(l+r)

>>1;

if(pos <= mid)

update

(lson,pos,c)

;else

update

(rson,pos,c)

;push_up

(rt);}

intquery

(int rt,

int mx)

intmain()

dfs(1,

1,1)

;dfs(1

,1);

int mx =0;

for(

int i=

1;i<=m ;i++

)build_tree(1

,1,a);

for(

int i=

1;i<=n ;i++)if

(tree[1]

.mx ==

0) ans[id[i]]=

0;else ans[id[i]]=

query(1

,tree[1]

.mx);}

for(

int i=

1;i<=n ;i++)}

return0;

}

hdu5029 樹鏈剖分

這題絕對好題。題意很簡單,也很容易想到樹鏈剖分,之後就不太好做了。開始想的是按顏色排序,然後每次處理一種顏色,求出最優解。這樣做的話,最壞情況會退化到n 2,不可接受。之後用線段樹維護,乙個節點只存在一種顏色,而且排序之後能保證在樹中顏色不會交叉,pushdown的時候可以將兩種都不是當前正在處理的...

hdu 5029 樹鏈剖分 鍊錶

因為是塗色問題,可以採用標記l 處 和r 處 1,把樹狀結構通過樹鏈剖分轉換成線性,利用線段樹維護顏色中出現的最多的,利用二分查詢能夠找到出現次數最多且序號最小的顏色 include include include include define max 200007 using namespace ...

hdu 3966(樹鏈剖分 線段樹)

題意 給出一棵樹,每個節點有一些敵人,有三種操作,i x,y,路徑上的所有點的人數 w。d x,y,路徑上的所有點的人數 w。q 節點x的人數。pragma comment linker,stack 1024000000,1024000000 include include include usin...