删边变为反向加边,一开始开了数组记录了边的编号,结果往下一翻才发现数据是加强版只得log的求编号了。
两点间最大路径最小值一定在最小生成树上。
先从小到大加边,然后就是裸的LCT了。
By:大奕哥
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=1500005; 4 int c[N][2],mx[N],fa[N],w[N],pos[N],rev[N],s[N]; 5 int n,m,Q; 6 bool isroot(int x){return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;} 7 void update(int x) 8 { 9 mx[x]=w[x];pos[x]=x; 10 if(mx[x]<mx[c[x][0]])mx[x]=mx[c[x][0]],pos[x]=pos[c[x][0]]; 11 if(mx[x]<mx[c[x][1]])mx[x]=mx[c[x][1]],pos[x]=pos[c[x][1]]; 12 return; 13 } 14 void pushup(int x) 15 { 16 if(rev[x]) 17 { 18 rev[x]^=1;rev[c[x][0]]^=1;rev[c[x][1]]^=1; 19 swap(c[x][0],c[x][1]); 20 } 21 return; 22 } 23 void rotate(int x) 24 { 25 int y=fa[x],z=fa[y],l,r; 26 l=c[y][1]==x;r=l^1; 27 if(!isroot(y))c[z][c[z][1]==y]=x; 28 fa[x]=z;fa[y]=x;fa[c[x][r]]=y; 29 c[y][l]=c[x][r];c[x][r]=y; 30 update(y);update(x); 31 return; 32 } 33 void splay(int x) 34 { 35 int top=0,i; 36 for(i=x;!isroot(i);i=fa[i])s[++top]=i;s[++top]=i; 37 for(i=top;i;--i)pushup(s[i]); 38 while(!isroot(x)) 39 { 40 int y=fa[x],z=fa[y]; 41 if(!isroot(y)) 42 { 43 if(c[y][0]==x^c[z][0]==y)rotate(x); 44 else rotate(y); 45 } 46 rotate(x); 47 } 48 return; 49 } 50 void access(int x) 51 { 52 int y=0; 53 while(x) 54 { 55 splay(x); 56 c[x][1]=y; 57 y=x;x=fa[x]; 58 } 59 return; 60 } 61 void mroot(int x) 62 { 63 access(x);splay(x);rev[x]^=1; 64 } 65 void cut(int x,int y) 66 { 67 mroot(x);access(y);splay(y);c[y][0]=fa[x]=0; 68 } 69 void link(int x,int y) 70 { 71 mroot(x);fa[x]=y;splay(x); 72 } 73 int f[N]; 74 inline int get(int x) 75 { 76 return x==f[x]?x:f[x]=get(f[x]); 77 } 78 int query(int x,int y) 79 { 80 mroot(x);access(y);splay(y); 81 return pos[c[y][0]]; 82 } 83 84 struct node 85 { 86 int x,y,w,id,f; 87 bool operator <(const node &b)const{ 88 return x<b.x||(x==b.x&&y<b.y); 89 } 90 }e[N]; 91 struct quer 92 { 93 int x,y,f,ans,id; 94 }q[100005]; 95 bool cmp(node a,node b){ 96 return a.w<b.w; 97 } 98 bool cmp2(node a,node b){ 99 return a.id<b.id; 100 } 101 int find(int x,int y) 102 { 103 int l=1,r=m; 104 while(l<=r) 105 { 106 int mid=l+r>>1; 107 if(e[mid].x<x||(e[mid].x==x&&e[mid].y<y))l=mid+1; 108 else if(e[mid].x==x&&e[mid].y==y)return mid; 109 else r=mid-1; 110 } 111 } 112 int main() 113 { 114 scanf("%d%d%d",&n,&m,&Q); 115 for(int i=1;i<=n;++i)f[i]=i; 116 for(int i=1;i<=m;++i) 117 { 118 scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].w); 119 if(e[i].y<e[i].x)swap(e[i].y,e[i].x); 120 } 121 sort(e+1,e+1+m,cmp); 122 for(int i=1;i<=m;++i) 123 { 124 e[i].id=i; 125 w[i+n]=e[i].w; 126 mx[i+n]=e[i].w; 127 pos[i+n]=i+n; 128 } 129 sort(e+1,e+1+m); 130 for(int i=1;i<=Q;++i) 131 { 132 scanf("%d%d%d",&q[i].f,&q[i].x,&q[i].y); 133 if(q[i].f==2) 134 { 135 if(q[i].x>q[i].y)swap(q[i].x,q[i].y); 136 int tmp=find(q[i].x,q[i].y); 137 e[tmp].f=1;q[i].id=e[tmp].id; 138 } 139 } 140 sort(e+1,e+1+m,cmp2); 141 for(int i=1;i<=m;++i) 142 { 143 if(e[i].f)continue; 144 int fx=get(e[i].x),fy=get(e[i].y); 145 if(fx!=fy) 146 { 147 f[fx]=fy; 148 link(e[i].x,i+n);link(e[i].y,i+n); 149 } 150 } 151 for(int i=Q;i;--i) 152 { 153 if(q[i].f==1)q[i].ans=w[query(q[i].x,q[i].y)]; 154 else 155 { 156 int tmp=query(q[i].x,q[i].y);int k=q[i].id; 157 if(w[tmp]>e[k].w) 158 { 159 cut(tmp,e[tmp-n].x);cut(tmp,e[tmp-n].y); 160 link(k+n,e[k].x);link(k+n,e[k].y); 161 } 162 } 163 } 164 for(int i=1;i<=Q;++i) 165 { 166 if(q[i].f==1)printf("%d\n",q[i].ans); 167 } 168 return 0; 169 }