傳送門
$sol$
最暴力的做法就是列舉最長鏈上的邊,然後再算一次所有的鏈長,更新$ans$.
這裡要求最大的最小,容易想到二分答案.對於二分的值$mid$,掃一遍所有的鏈,若鏈長小於等於$mid$,那麼是合法的不需要處理的.否則,就記錄鏈上所有的邊經過的次數$+1$.最後找到被經過次數等於鏈長大於$mid$的鏈數的最大的邊,改成0,再看最長鏈是否小於等於$mid.$如果沒有這樣的邊,那麼$mid$顯然是不合法的,是偏小的.
維護邊經過的次數樹上差分.
$code$
#include#define il inlineview code#define ri register int
#define go(i,a,b) for(ri i=a;i<=b;++i)
#define yes(i,a,b) for(ri i=a;i>=b;--i)
#define e(i,u) for(ri i=b[u];i;i=a[i].nt)
#define mem(a,b) memset(a,b,sizeof(a))
#define ll long long
#define db double
#define inf 2147483647
using
namespace
std;
il int
read()
while(c>='
0'&&c<='9')
return x*y;
}const
int n=300010
;int n,m,b[n],ct,dep[n],f[n][19],dis[n],t[n],num,dd,as
;bool
fl;struct nda[n*2
];struct nd1c[n];
il void add(ri u,ri v,ri w);b[u]=ct;}
il void
build(ri u,ri fa)
}il
intlca(ri u,ri v)
il bool cmp(nd1 x,nd1 y)
il int
dfs(ri u)
ret+=t[u];
return
ret;
}il
bool
ck(ri x)
dfs(1);
if(!fl)return0;
if(c[1].l-dd>x)return0;
return1;
}int
main()
build(
1,0);
go(i,
1,m);}
sort(c+1,c+n+1
,cmp);
ri l=0,r=c[1].l+1
;
while(l<=r)
printf(
"%d\n
",as
);
return0;
}
luogu2680 運輸計畫
很明顯,由於是求最長路的最小值,我們可以使用二分求解.我們二分乙個長度 mid 將所有使得 dis u,v 大於 mid 的點對 u,v 找出,設總共有 m 條這樣的邊,那麼我們需要改變的改變邊一定是被這 m 條邊都經過的邊,所以我們只需要找到滿足這個要求的長度最大的改變邊使得這 m 條邊中最長的一...
Luogu2680 運輸計畫
我們對每條邊 i 單獨考慮,那麼設 v i 為這條邊的長度,經過它的路徑長度集合為 s 未經過它的路徑長度集合為 t ans i max begin s v i t end ans min ans i 對於 s 我們直接對於一條長度為 l 的路徑,該路徑上的邊都對 l 取 max 用樹鏈剖分很容易處...
luogu2680 運輸計畫
首先二分列舉答案t,考慮刪去的邊應滿足的條件 所有大於 t的鏈全部經過且長度不小於最長鏈 t,第二個條件很好判斷,考慮第乙個條件。先考慮有祖先 後代關係的鏈,用如果把這條鏈到 1看成乙個序列,那麼差分一下再 dfs一遍就可以對這條鏈上每乙個點打上標記。然後沒有祖先 後代關係的鏈,同樣可以分解成兩條鏈...