BZOJ3784樹上的路徑

2022-07-13 19:33:15 字數 1725 閱讀 7867

題目描述

給定乙個n個結點的樹,結點用正整數1..n編號。每條邊有乙個正整數權值。用d(a,b)表示從結點a到結點b路邊上經過邊的權值。其中要求a題解

把每次點分治時的dfs序寫下來,假設我們在乙個位置找能夠和它拼成一條鏈的另乙個位置,可以發現那些位置的順序在dfs序上構成了一段連續區間,用st表+堆維護。

注意在進佇列之前先內啥一下。

**

#include#include

#include

#include

#define n 50002

#define m 16

using

namespace

std;

int tot,head[n],lo[n*m],st[m][n*m],size[n],dp[n],sum,now,deep[n],root,n,p[m][n*m];

bool

vis[n];

intstart,ed;

inline

intrd()

while(isdigit(c))

return f?-x:x;

}struct edgee[n<<1

];inline

void add(int u,int v,int l)

struct

node

intcalc()

bool

operator

<(const node &b)const

}pa[n*m];

priority_queue

q;void getroot(int u,int

fa) dp[u]=max(dp[u],sum-size[u]);

if(dp[u]u;

}void getsize(int u,int

fa)}

void getdeep(int u,int

fa)}

inline

void calc(int

u); start=now;ed=now;

for(int i=head[u];i;i=e[i].n)if(!vis[e[i].to])

}void solve(intu)}

intmain()

dp[root=n+1]=n+1;sum=n;

getroot(

1,0);getsize(root,0

); solve(root);

for(int i=1;(1

for(int j=1;j+(1

<1

<=now;++j)

st[i][j]=max(st[i-1][j],st[i-1][j+(1

<1)]),p[i][j]=st[i-1][j]>=st[i-1][j+(1

<1)]?p[i-1][j]:p[i-1][j+(1

<1

)];

for(int i=2;i<=now;++i)lo[i]=lo[i>>1]+1

;

for(int i=1;i<=now;++i)pa[i]=node(pa[i].now,pa[i].l,pa[i].r),q.push(pa[i]);///

care !!!!

for(int i=1;i<=k;++i)

return0;

}

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 樹上的路徑

樹的點分治,在分治的時候將所有點到根的距離依次放入乙個陣列q中。對於一棵子樹裡的點,合法的路徑一定是q l q r 的某個數加上自己到重心的距離。定義五元組 v,l,m,r,w 表示當前路徑長度為v,在 l,r 裡選出最大值m,並加上w。用大根堆維護這些五元組,每次取出v最大的元素,並擴充套件出 l...

BZOJ3784 樹上的路徑

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