luogu P2387 NOI2014 魔法森林

2022-02-05 01:38:16 字數 1375 閱讀 7412

傳送門

這題似乎不好直接做,可以考慮按照\(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...