BZOJ3784 樹上的路徑

2021-09-07 03:49:00 字數 1081 閱讀 8938

樹的點分治,在分治的時候將所有點到根的距離依次放入乙個陣列q中。

對於一棵子樹裡的點,合法的路徑一定是q[l]..q[r]的某個數加上自己到重心的距離。

定義五元組(v,l,m,r,w),表示當前路徑長度為v,在[l,r]裡選出最大值m,並加上w。

用大根堆維護這些五元組,每次取出v最大的元素,並擴充套件出[l,m-1]以及[m+1,r]兩個狀態,用線段樹查詢區間最大值。

時間複雜度$o(n\log^2n+m\log n)$。

#include#includeusing namespace std;

const int n=50010,m=800000;

int n,m,i,x,y,z,g[n],v[n<<1],w[n<<1],ok[n<<1],nxt[n<<1],ed;

int all,f[n],son[n],now;

int l,r,q[m],cnt,val[2100000],cp;

struct p

p(int _v,int _l,int _m,int _r=0,int _w=0)

inline bool operator<(const p&b)const

void build(int x,int a,int b)

int mid=(a+b)>>1;

build(x<<1,a,mid),build(x<<1|1,mid+1,b);

val[x]=merge(val[x<<1],val[x<<1|1]);

}int ask(int x,int a,int b,int c,int d)

inline void extend(int l,int r,int w)

inline void add(int x,int y,int z)

void findroot(int x,int y)

if(all-son[x]>f[x])f[x]=all-son[x];

if(f[x]}void dfs(int x,int y,int dis)

void solve(int x)

}int main()

return 0;

}

bzoj3784 樹上的路徑

time limit 10 sec memory limit 256 mb submit 789 solved 266 submit status discuss 給定乙個n個結點的樹,結點用正整數1.n編號。每條邊有乙個正整數權值。用d a,b 表示從結點a到結點b路邊上經過邊的權值。其中要求a ...

BZOJ3784樹上的路徑

題目描述 給定乙個n個結點的樹,結點用正整數1.n編號。每條邊有乙個正整數權值。用d a,b 表示從結點a到結點b路邊上經過邊的權值。其中要求a題解 把每次點分治時的dfs序寫下來,假設我們在乙個位置找能夠和它拼成一條鏈的另乙個位置,可以發現那些位置的順序在dfs序上構成了一段連續區間,用st表 堆...

BZOJ3784 樹上的路徑

思路1 澱粉質。用priority queue維護前 m 長的路徑的長度。用multiset維護點分治時,之前所有子樹的路徑長度,然後對於新子樹中的每一條路徑,在multiset中從大往小列舉另一半路徑拼一起並嘗試加入優先佇列。如果加入失敗,那麼對於這個點,集合中再往前的數也不會成功,可以直接跳掉。...