BZOJ 2599 Race 點的分治

2021-12-29 22:06:47 字數 2497 閱讀 8290

題意:給一棵樹,每條邊有權.求一條路徑,權值和等於k,且邊的數量最小. (我會告訴你這就是題面?)

bzoj的題就是好啊!一句話題意,贊乙個。

這道題的思路還是點分治 ,類似於前面那篇文章裡的兩題,只不過轉換成了求最小而不是計數,,,

每次找好重心u後,我們只考慮以u為根的子樹,u的子樹可以分治下去搞。

我們只考慮經過根的路徑

由前面兩題,可以很輕鬆的想到這樣乙個方法:

先搜出當前樹所有的二元組(w,dep),然後排序,掃瞄,但是注意,有可能兩個點來自於同一棵子樹,如果給二元組加乙個資訊屬於哪顆子樹,就變成了三元組。。。。判斷兩個元素是否滿足條件需要滿足三個資訊,很是複雜啊。。不過我還是用這個方法寫了老半天,最後實在搞不定就想其他方法了。

還是由以前做過的一些樹形dp得到的啟發,我們一棵一棵子樹的去合併,也就是在當前子樹找乙個點(w,dep),在前面的子樹找乙個點,這個點

到根的權值和是 k-w ,並且深度最小,我們就記為dp[k-w]好了,(這種方法在合併子樹的問題上還是蠻常用的),然後我們每次先詢問再更新dp陣列就好了,要注意dp陣列的初始化,不能全部都清空,要不果斷tle。。。。

這題的資料應該還是蠻好造的吧。。。。

附上**:速度略慢啊,跑了17s多

[cpp]

#include  

#include  

#include  

#include  

using namespace std; 

const int maxn = 222222; 

struct divided_conquer  

edge(int v,int w): v(v),w(w)  

}; bool del[maxn]; 

vector e[maxn]; 

int n , k; 

int size[maxn] , opt[maxn] ,dp[1000010]; 

vector tnode ; 

vector >  now; 

void dfs(int u,int f) 

} } 

int get_root(int u) 

} return ans; 

} vector all ; 

void get_dis(int u,int len,int dep,int fa) 

} } 

inline void merge(vector > a) 

} } 

void solve(int u) 

} for(vector::iterator it = all.begin(); it != all.end(); it++)  

del[u] = true; 

for(vector::iterator it = e[u].begin(); it != e[u].end(); it++)  

} } 

inline void calc(vector >now) 

} } 

} inline  void update(int &x,int cmp) 

void init() 

} int ans; 

}sol; 

int main() 

#include

#include

#include

#include

using namespace std;

const int maxn = 222222;

struct divided_conquer

edge(int v,int w): v(v),w(w)

};bool del[maxn];

vector e[maxn];

int n , k;

int size[maxn] , opt[maxn] ,dp[1000010];

vector tnode ;

vector >  now;

void dfs(int u,int f)}}

int get_root(int u)

}return ans;

}vector all ;

void get_dis(int u,int len,int dep,int fa)}}

inline void merge(vector > a)

}}    void solve(int u)

}for(vector::iterator it = all.begin(); it != all.end(); it++)

del[u] = true;

for(vector::iterator it = e[u].begin(); it != e[u].end(); it++) }}

inline void calc(vector >now)

}}    }

inline  void update(int &x,int cmp)

void init()

}int ans;

}sol;

int main()

BZOJ3730 點分樹 震波

鏈結自己找,bzoj還沒開 也很顯然是點分樹維護,對每個點開兩個樹狀陣列,維護點分樹上子樹之和,然後修改詢問仍然暴力爬樹,詢問也是用兩個樹狀陣列作差消掉當前子樹影響 code include using namespace std inline intread while isdigit ch re...

bzoj3730 震波(點分樹 bit)

傳送門 點分樹板題。然而並沒有遇到卡常之類的事。對於分出來的每一層用兩棵bit bitbi t動態維護到自己距離不超過k kk的與到自己點分樹父親距離不超過k kk的點數。include define ri register int using namespace std const int rle...

BZOJ 1095 捉迷藏 動態點分治 點分樹

1095 zjoi2007 hide 捉迷藏 time limit 40 sec memory limit 256 mb submit 4152 solved 1756 submit status discuss description 捉迷藏 jiajia和wind是一對恩愛的夫妻,並且他們有很多...