題目描述
給定乙個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中從大往小列舉另一半路徑拼一起並嘗試加入優先佇列。如果加入失敗,那麼對於這個點,集合中再往前的數也不會成功,可以直接跳掉。...