傳送門
這題似乎不好直接做,可以考慮按照\(a_i\)公升序排序,然後依次加邊更新答案
具體實現方法是用lct維護當前的樹,這裡需要維護鏈上最大的\(b_i\).每次加一條邊,如果加完以後沒有環直接加,否則找出鏈上最大的\(b_i\),如果這個\(b_i\)比當前的\(b_i\)小,加了肯定不優,否則就把那條邊斷掉,加上這條邊.每次用當前\(a_i\)和1到n鏈上最大\(b_i\)更新答案
#include#define ll long long
#define db long double
#define il inline
using namespace std;
const int n=1e5+10;
il ll rd()
while(ch>='0'&&ch<='9')
return x*w;
}int n,m,w[n],po[n][2],tt;
int fa[n],ch[n][2],id[n],vi[n];
bool tg[n];
bool nrt(int x)
void psup(int x)
void rev(int x)
void psdn(int x)
void ppush(int x)
void rot(int x)
void spl(int x)
psup(x);
}void acs(int x)
void mkrt(int x)
int fdrt(int x)
void split(int x,int y)
void link(int x,int y,int z)
acs(y),spl(y);
int ii=id[y];
if(w[ii]<=z) return;
mkrt(po[ii][0]),acs(po[ii][1]),spl(ii);
fa[po[ii][0]]=fa[po[ii][1]]=ch[ii][0]=ch[ii][1]=0,psup(ii);
w[ii]=z,po[ii][0]=x,po[ii][1]=y;
mkrt(x),mkrt(y);
fa[x]=fa[y]=ii;
}struct edge
}e[n];
int main()
; }
sort(e+1,e+m+1);
tt=n,w[0]=-(1<<30);
int ans=1<<30;
for(int i=1;i<=m;++i)
printf("%d\n",ans<(1<<29)?ans:-1);
return 0;
}
P2387 NOI2014 魔法森林
p2387 noi2014 魔法森林 這題目花了點時間題解沒圖,其中一些操作不夠簡潔,常數比較大,都說 lct 常數小 時限 3000ms 最大點 500ms 反正過了 首先考慮做法 排序 a 順序加邊,然後動態維護最大 b 使生成樹最小,其中貢獻為最大的 b 這題是動態的,所以考慮 lct 但不同...
P2387 NOI2014 魔法森林(LCT)
將所有邊按a從小到大排序,加入一條新邊 u,v 時,檢查原先u和v是否連通,若連通則斷開舊路徑,新路徑上最大的b和新加入的邊的a相加,看能否更新答案。既然是動態加邊和刪邊,便考慮用lct。要查詢兩點間路徑上的最大值,所以點和邊都要建節點,並且維護最大的b和其對應的邊的標號。當加入新邊檢查是否兩點已聯...
P2387 NOI2014 魔法森林(LCT)
p2387 noi2014 魔法森林 lct邊權維護經典題 咋維護呢?邊化為點,邊權變點權。本題中我們把邊對關鍵字a進行排序,動態維護關鍵字b的最小生成樹 加邊後出現環咋辦?splay維護最大邊的編號,找到最大邊刪除再加新邊就ok辣 include include using namespace s...