time limit: 10 sec
memory limit: 256 mb
submit: 789
solved: 266 [
submit][
status][
discuss]
給定乙個n個結點的樹,結點用正整數1..n編號。每條邊有乙個正整數權值。用d(a,b)表示從結點a到結點b路邊上經過邊的權值。其中要求a
第一行兩個正整數n,m
下面n-1行,每行三個正整數a,b,c(a,b<=n,c<=10000)。表示結點a到結點b有一條權值為c的邊。
共m行,如題所述.
5 10
1 2 1
1 3 2
2 4 3
2 5 4 77
6 5
4 4
3 3
2 1
n<=50000,m<=min(300000,n*(n-1) /2 ) [
submit][
status][
discuss]
先把樹轉換成點分治序列,然後做法同noi2010超級鋼琴
**:
#include#include#include#include#include#includeusing namespace std;
const int maxn = 50100;
struct edge;
int s[maxn * 20];
struct data
};int n,m;
int maxid[20 * maxn][20],length[20 * maxn];
priority_queueq;
vectore[maxn];
bool vis[maxn];
int siz[maxn],weight[maxn],id,dfn[maxn],pos[20 * maxn],cmax[20 * maxn],tot;
inline int getint()
inline void dfs_siz(int u,int fa,int t)
siz[u]++;
weight[u] = max(weight[u],t - siz[u]);
if (weight[u] < weight[id]) id = u;
}inline void cal(int u,int fa)
}inline void st_init()
for (int i = 1; i <= tot; i++) maxid[i][0] = i;
for (int j = 1; j <= 20; j++)
for (int i = 1; i <= tot; i++) }
inline int query_maxid(int l,int r)
inline void solve(int u)
cmax[dfn[u]] = dfn[u];
for (int i = dfn[u] + 1; i <= tot; i++)
); }
vis[u] = 1;
for (int i = 0; i < e[u].size(); i++) }
int main()
); e[v].push_back((edge));
} dfs_siz(1,0,0);
weight[0] = 2147483647;
solve(1);
st_init();
for (int i = 1; i <= m; i++)
); if (nl <= r) q.push((data));
} return 0;
}
BZOJ3784 樹上的路徑
樹的點分治,在分治的時候將所有點到根的距離依次放入乙個陣列q中。對於一棵子樹裡的點,合法的路徑一定是q l q r 的某個數加上自己到重心的距離。定義五元組 v,l,m,r,w 表示當前路徑長度為v,在 l,r 裡選出最大值m,並加上w。用大根堆維護這些五元組,每次取出v最大的元素,並擴充套件出 l...
BZOJ3784樹上的路徑
題目描述 給定乙個n個結點的樹,結點用正整數1.n編號。每條邊有乙個正整數權值。用d a,b 表示從結點a到結點b路邊上經過邊的權值。其中要求a題解 把每次點分治時的dfs序寫下來,假設我們在乙個位置找能夠和它拼成一條鏈的另乙個位置,可以發現那些位置的順序在dfs序上構成了一段連續區間,用st表 堆...
BZOJ3784 樹上的路徑
思路1 澱粉質。用priority queue維護前 m 長的路徑的長度。用multiset維護點分治時,之前所有子樹的路徑長度,然後對於新子樹中的每一條路徑,在multiset中從大往小列舉另一半路徑拼一起並嘗試加入優先佇列。如果加入失敗,那麼對於這個點,集合中再往前的數也不會成功,可以直接跳掉。...