1. 程式人生 > >bzoj2594 [Wc2006]水管局長資料加強版(lct+kruskal+離線)

bzoj2594 [Wc2006]水管局長資料加強版(lct+kruskal+離線)

考慮離線操作,倒著做,就是維護不斷往裡加邊的最小生成樹。具體做法與魔法森林差不多。
至於如何找到一條邊的標號,可以二分查詢來做。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define N 2100010
#define ll long long
#define inf 0x3f3f3f3f
inline char gc(){
    static char buf[1<<16],*S,*T;
    if
(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;} return *S++; } inline int read(){ int x=0,f=1;char ch=gc(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();} while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc(); return x*f; } int n,m,Q,fa[N],c[N][2],v[N],mx[N],qq[N],tot=0
,pa[100010],ans[100010]; bool rev[N],bad[N>>1]; struct quer{ int op,x,y,id; }q[100010]; struct edge{ int x,y,val,id; edge(){}; edge(int _x,int _y){x=_x;y=_y;} friend bool operator<(edge a,edge b){return a.x==b.x?a.y<b.y:a.x<b.x;} }e[N>>1]; inline bool cmp(edge a,edge b){return
a.val<b.val;} inline bool cmp2(edge a,edge b){return a.id<b.id;} inline int find(int x){return x==pa[x]?x:pa[x]=find(pa[x]);} inline bool isroot(int x){return x!=c[fa[x]][0]&&x!=c[fa[x]][1];} inline void update(int x){ int l=c[x][0],r=c[x][1]; if(v[mx[l]]>=v[mx[r]]&&v[mx[l]]>=v[x]) mx[x]=mx[l]; else if(v[mx[r]]>v[x]) mx[x]=mx[r];else mx[x]=x; } inline void pushdown(int p){ if(!rev[p]) return;rev[p]=0;swap(c[p][0],c[p][1]); rev[c[p][0]]^=1;rev[c[p][1]]^=1; } inline void rotate(int x){ int y=fa[x],z=fa[y],l=x==c[y][1],r=l^1; if(!isroot(y)) c[z][y==c[z][1]]=x; fa[c[x][r]]=y;fa[y]=x;fa[x]=z; c[y][l]=c[x][r];c[x][r]=y;update(y);update(x); } inline void splay(int x){ int top=0;qq[++top]=x; for(int xx=x;!isroot(xx);xx=fa[xx]) qq[++top]=fa[xx]; while(top) pushdown(qq[top--]); while(!isroot(x)){ int y=fa[x],z=fa[y]; if(!isroot(y)){ if(x==c[y][1]^y==c[z][1]) rotate(x); else rotate(y); }rotate(x); } } inline void access(int x){ int y=0;while(x){splay(x);c[x][1]=y;update(x);y=x;x=fa[x];} } inline void makeroot(int x){ access(x);splay(x);rev[x]^=1; } inline void link(int x,int y){ makeroot(x);fa[x]=y; } inline void cut(int x,int y){ makeroot(x);access(y);splay(y);c[y][0]=fa[x]=0,update(y); } inline int qmax(int x,int y){ makeroot(x);access(y);splay(y);return mx[y]; } int main(){ // freopen("a.in","r",stdin); n=read();m=read();Q=read(); for(int i=1;i<=m;++i){ e[i].x=read(),e[i].y=read(),e[i].val=read();v[i+n]=e[i].val;mx[i+n]=i+n; if(e[i].x>e[i].y) swap(e[i].x,e[i].y);e[i].id=i; }sort(e+1,e+m+1); for(int i=1;i<=Q;++i){ q[i].op=read();q[i].x=read();q[i].y=read(); if(q[i].op==1){q[i].id=++tot;continue;} if(q[i].x>q[i].y) swap(q[i].x,q[i].y); q[i].id=lower_bound(e+1,e+m+1,edge(q[i].x,q[i].y))->id;bad[q[i].id]=1; }sort(e+1,e+m+1,cmp); for(int i=1;i<=n;++i) pa[i]=i;int ofo=0; for(int i=1;i<=m;++i){ if(ofo==n-1) break; if(bad[e[i].id]) continue; int x=e[i].x,y=e[i].y,xx=find(x),yy=find(y); if(xx==yy) continue;ofo++;pa[xx]=yy;link(x,e[i].id+n);link(e[i].id+n,y); }sort(e+1,e+m+1,cmp2); for(int i=Q;i;--i){ if(q[i].op==1){ans[q[i].id]=e[qmax(q[i].x,q[i].y)-n].val;continue;} int x=q[i].x,y=q[i].y,t=q[i].id,old=qmax(x,y); if(v[t+n]>=v[old]) continue;cut(e[old-n].x,old);cut(e[old-n].y,old); link(x,t+n);link(t+n,y); }for(int i=1;i<=tot;++i) printf("%d\n",ans[i]); return 0; }

相關推薦

bzoj2594 [Wc2006]水管局長資料加強lct+kruskal+離線

考慮離線操作,倒著做,就是維護不斷往裡加邊的最小生成樹。具體做法與魔法森林差不多。 至於如何找到一條邊的標號,可以二分查詢來做。 #include <cstdio> #include <cstring> #include <al

[BZOJ2594][Wc2006]水管局長資料加強kruskal+lct

題目描述 傳送門 題解 寫lct就應該有那種誓死不看板子的氣魄。 這道題思路還是很清晰的,維護一棵最小生成樹,每一次找樹鏈上權值最大的邊 刪邊變成倒序加邊 最開始的時候用沒有刪的邊kruskal直接最小生成樹 動態的話就是維護一棵lct,每一次加邊

BZOJ2594 [Wc2006]水管局長資料加強LCT

Description SC省MY市有著龐大的地下水管網路,嘟嘟是MY市的水管局長(就是管水管的啦),嘟嘟作為水管局長的工作就是:每天供水公司可能要將一定量的水從x處送往y處,嘟嘟需要為供水公司找到一條從A至B的水管的路徑,接著通過資訊化的控制中心通知路徑上的

bzoj2594: [Wc2006]水管局長資料加強

題目大意:給定一個簡單圖,支援刪邊,每次詢問兩點間 最大邊權值最小的路徑。 思路:題目中權值在邊上,而LCT維護的全值在點上,所以要先轉化,對於連線x和y的第i條路徑,把邊變成第i+n個點,然後把權值放到邊點上,所有真正的點權值賦為0,這也是維護邊權的常用方法。接著就是一

bzoj2594】[Wc2006]水管局長資料加強 link cut tree

好久的坑了,今天終於填上了。 一直想總結一下LCT,結果發現難題都不會做。 離線處理,因為刪邊比較難做,所以我們倒著做變成加邊操作。 問題轉化成加邊維護最小生成樹,用lct維護一下最大的邊是哪一條,一旦新加入的邊形成環了,那麼看一看環上最大的邊和新加入的邊哪個大,如果新加入

BZOJ 2594: [Wc2006]水管局長資料加強(lct)

傳送門 解題思路   一道\(lct\)維護動態最小生成樹。剛開始寫了一遍瘋狂\(Re\),冷靜了一下重新寫了一遍終於過了。首先題目中要求兩點之間最大值的最小值,其實就是維護一個最小生成樹,每次詢問最大值。要將刪邊轉化成加邊操作,就是倒著處理,這裡用\(set\)和\(map\)就比較方便。然後還要把邊權

[動態樹 LCT] BZOJ 2594 [Wc2006]水管局長資料加強

動態樹模板題 最開始加邊用Kruskal比較快,不用LCT,然後再用LCT維護最小生成樹 話說這道題小資料範圍的正解是什麼.... PS:以前LCT的求根都是打錯的,沒有pushdown() #include<cstdio> #include<cstd

BZOJ 2594: [Wc2006]水管局長資料加強(LCT+最小生成樹+離線)

題目戳我 Solution 題目大意:就是讓你維護一棵動態的最小生成樹, 並詢問兩點路徑中邊權最大值。 很明顯,用LCT來做這個。有幾個關鍵點: ①刪邊維護mst不好搞,我們離線然後刪邊變加邊。 ②一開始用kruskal搞出底圖的mst,然後加

BZOJ 2594 [Wc2006]水管局長資料加強

由於題目有刪除操作,所以我們不妨倒敘列舉,把刪邊變成加邊。某人還起了個好聽的名字叫“時光倒流”…… 之後用動態樹維護一下動態最小生成樹就行了,每加入一條邊就用動態樹樹找出兩點見最長邊,比較大小看是否能替換就行了。 這裡還有一個小技巧,就是二分邊標號來找出每個

BZOJ 2594 [Wc2006]水管局長資料加強 LCT

題意:連結 方法: LCT 解析: 搞了一個上午加1個小時的題,TM最後大錯誤居然是排序元素太多排不回原來的樣子! 我要重新學排序! 這題是用LCT維護動態最小生成樹,但是最小生成樹上刪邊應該是做不到的,所以我們可以離線操作,之後先把所

BZOJ2594】【WC2006水管局長資料加強

【題目連結】【思路要點】若題目僅包含詢問操作,顯然我們只需保留一棵圖的最小生成樹,在樹上詢問兩點間邊權的最大值即可。而本題中多了一種刪邊操作,但沒有強制線上,因此,我們可以將操作離線,轉化為加邊操作。用LinkCutTree維護動態最小生成樹即可。時間複雜度\(O((M+Q)

[BZOJ2594][Wc2006][LCT]水管局長資料加強

題意 給一張圖,每次操作或詢問所有u到v路徑上邊權最大值的最小值,或刪除一條邊 離線,反過來操作,刪邊變成加邊,用LCT維護圖的聯通就行。 #include <cstdio> #include <iostream> #inc

BZOJ 3514: Codechef MARCH14 GERALD07加強LCT + 主席樹

typename pda 在線的 發現 () rev rdo getc nod 題意 \(N\) 個點 \(M\) 條邊的無向圖,詢問保留圖中編號在 \([l,r]\) 的邊的時候圖中的聯通塊個數。 \(K\) 次詢問強制在線。 \(1\le N,M,K \le 200,0

bzoj2594: [Wc2006]水管局長數據加強

date get push roo 表示 sort 選擇 mit 管道 地址:http://www.lydsy.com/JudgeOnline/problem.php?id=2594 題目: 2594: [Wc2006]水管局長數據加強版 Time Limit:

BZOJ2594 [Wc2006]水管局長數據加強LCT

最短 一次 read amp std 之前 應輸入 NPU 進入 Description SC省MY市有著龐大的地下水管網絡,嘟嘟是MY市的水管局長(就是管水管的啦),嘟嘟作為水管局長的工作就是:每天供水公司可能要將一定量的水從x處送往y處,嘟嘟需要為供水公司找到一條從A至

BZOJ 3674 可持久化並查集加強主席樹變形

als ret desc scan sync scanf ops 只需要 ica 3673: 可持久化並查集 by zky Time Limit: 5 Sec Memory Limit: 128 MB Submit: 2515 Solved: 1107 [

bzoj5037 線段樹練習4加強暴力分塊

log del string 技術分享 iostream || getc code click   求大爺教線段樹怎麽寫啊QAQ   只會寫分塊...一開始腦抽寫成了O(NKlogN)還被CZL大爺嘲諷了一發T T   f[i][j]表示在第i塊中,模k為j的數有幾個,

NYOJ 290 動物統計加強字典樹題

動物統計加強版 時間限制:3000 ms  |  記憶體限制:150000 KB 難度:4 輸入 第一行輸入動物名字的數量N(1<= N <= 4000000),接下來的N行輸入N個字串表示動物的名字(字串的長度不超過10,字串全為小寫字母,並且只有一

三維一邊推:最長公共子序列加強三串LCS CAIOJ - 1073 dp lcs

題解 與二位lcs類似 列舉三個串的每個位置 狀態轉移考慮5種情況 abc當前位置全相等則由3個串長度全-1的位置轉移過來 lcs+1 ab相等但不與c相等 則由ab長度都-1或c長度-1取max轉移過來 ac相等但不與b相等和bc相等但不與a相等類似 abc互不相等則由a、b或c長度-

NYOJ 290 動物統計加強字典樹姍姍來遲

// trietree.cpp : 定義控制檯應用程式的入口點。//#include<cstdio>#include<iostream>#include<string.h>using namespace std;const int num_chars = 26;