hdu5029 樹鏈剖分

2021-06-26 03:00:47 字數 1859 閱讀 7083

這題絕對好題。

題意很簡單,也很容易想到樹鏈剖分,之後就不太好做了。

開始想的是按顏色排序,然後每次處理一種顏色,求出最優解。這樣做的話,最壞情況會退化到n^2,不可接受。

之後用線段樹維護,乙個節點只存在一種顏色,而且排序之後能保證在樹中顏色不會交叉,pushdown的時候可以將兩種都不是當前正在處理的顏色給覆蓋掉,不過這樣寫有個bug一直沒解決掉,就是如果更新一直在葉子節點,如何確定該不該覆蓋存在問題,這種寫法又掛掉了。

這題做完之後,剖分之後的樹在腦中再也不是樹,是鏈。

具體看**:

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

#include #include #include #include #include #define lson l,m,rt<<1

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

#define delf int m=(l+r)>>1

using namespace std;

const int max=100010;

int top[max];

int num[max];

int son[max];

int fa[max];

int dep[max];

int pos[max]; //原樹->新鏈

int cpos[max]; //新鏈->原樹

int cn[max<<2]; //每個節點當前種子型別的種子數

int cz[max<<2]; //每個節點當前種子型別

int ans[max]; //答案

int head[max];

vector mv[max]; //每個節點的標記

int n,m,curz,cnt,sss;

struct edge

edge[max<<1];

struct path

path[max];

void init() //初始化

cnt=0;

sss=1;

return ;

}void add_edge(int a,int b,int i) //建樹

void dfs1(int u,int d,int f)

next=edge[next].next;

}return ;

}void dfs2(int u,int t)

return ;

}//剖分結束

//線段樹維護的是每種顏色的數量,cz代表顏色,cn代表數量

void swap(int &a,int &b)

void pushup(int rt)

else

return ;

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

void update(int k,int v,int l,int r,int rt)

delf;

if (k<=m)

update(k,v,lson);

else

update(k,v,rson);

pushup(rt);

return ;

}//線段樹結束

//標記首尾節點部分

void solve(int x,int y,int z)

ans[cpos[i]]=cz[1]; //當前點維護結束之後,根節點的就是答案

}return ;

}int main()

{ while (scanf("%d%d",&n,&m)&&n+m)

{init();

for (int i=1;i

hdu 5029 樹鏈剖分 鍊錶

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

HDU 5029 樹鏈剖分 權值線段樹

題目鏈結 題意 給定一顆n個結點的樹,進行m次染色操作,對於每一次染色操作是選擇樹上的一條路徑,將路徑上所有節點都染上第z zz種顏色。輸出m次操作以後,每乙個節點上染色次數最多的顏色。1 n m,z 1 e5 1 n,m,z 1e5 1 n m,z 1 e5思路 對於樹上的路徑操作,自然能夠想到使...

樹鏈剖分 樹鏈剖分講解

好了,這樣我們就成功解決了對樹上修改查詢邊權或點的問題。下面放上 vector v maxn int size maxn dep maxn val maxn id maxn hson maxn top maxn fa maxn 定義 int edge 1,num 1 struct tree e ma...