luogu P3206 [HNOI2010]城市建设
作者:互联网
题面传送门
思维不够就拿数据结构来凑啊qwq
因为cdq的方法太神奇了,所以蒟蒻只能写LCT了。
因为LCT可以维护加边的最小生成树,所以考虑用LCT来维护。
但是有一个问题这道题还有删边。
但是我们惊奇地发现LCT是可以撤销的。
所以可以上线段树分治转删边为加边,然后复杂度要上去一个log
不过不得不说LCT的常数是真的大。跑的完全不像两个log的样子。
code:
#include<cstdio>
#include<vector>
#define I inline
#define l(x) x<<1
#define r(x) x<<1|1
#define ll long long
using namespace std;
int n,m,k,x[100039],y[100039],z[100039],last[100039],a,b;
ll ans[100039],tot;
struct pai{
int id,w;
pai operator +(const pai &s)const{return w>s.w?(pai){id,w}:s;}
}now;
vector<pai> f[400039],g[400039];
vector<int> flag[400039];
I void swap(int &x,int &y){x^=y^=x^=y;}
struct linkcuttree{
int fa[100039],l[100039],r[100039],flag[100039],st[100039],sh;pai f[100039],sum[100039];
I void up(int x){sum[x]=sum[l[x]]+sum[r[x]]+f[x];}
I void push(int x){x&&(swap(l[x],r[x]),flag[x]^=1);}
I void pushdown(int x){flag[x]&&(push(l[x]),push(r[x]),flag[x]=0);}
I int child(int x){return l[fa[x]]==x||r[fa[x]]==x;}
I int wrt(int x){return l[fa[x]]==x;}
I void rotate(int x){
int y=fa[x],z=fa[y],b=(l[y]==x?r[x]:l[x]);child(y)&&((y==l[z]?l[z]:r[z])=x);
(x==l[y])?(r[x]=y,l[y]=b):(l[x]=y,r[y]=b);fa[x]=z;fa[y]=x;b&&(fa[b]=y);up(y);up(x);
}
I void splay(int x){
int y=x;st[sh=1]=x;while(child(y)) st[++sh]=y=fa[y];while(sh) pushdown(st[sh--]);
while(child(x)) child(fa[x])&&(rotate(wrt(x)^wrt(fa[x])?x:fa[x]),0),rotate(x);
}
I void access(int x){for(int y=0;x;x=fa[y=x])splay(x),r[x]=y,up(x);}
I void makeroot(int x){access(x);splay(x);push(x);}
I void split(int x,int y){makeroot(y);access(x);splay(x);}
I void link(int x,int y){makeroot(x);fa[x]=y;}
I void cut(int x,int y){split(x,y);l[x]=fa[y]=0;up(x);}
I int findroot(int x){access(x);splay(x);while(l[x]) pushdown(x),x=l[x];return splay(x),x;}
}s;
I void link(int x,int y,pai a){s.f[a.id+n]=s.sum[a.id+n]=a;if(s.findroot(x)==s.findroot(y))printf("-1\n");s.link(x,a.id+n);s.link(y,a.id+n);}
I void cut(int x,int y,int id){s.cut(x,id+n);s.cut(y,id+n);}
I void get(int x,int y,pai z,int l=0,int r=k,int now=1){
if(x<=l&&r<=y) return (void)(f[now].push_back(z));int m=l+r>>1;
(x<=m)&&(get(x,y,z,l,m,l(now)),0);(y>m)&&(get(x,y,z,m+1,r,r(now)),0);
}
I void find(int l=0,int r=k,int now=1){
pai tmp,nows;int m=l+r>>1,i;
for(i=0;i<f[now].size();i++){
tmp=f[now][i];flag[now].push_back(0);g[now].push_back((pai){0,0});
if(s.findroot(x[tmp.id])^s.findroot(y[tmp.id])) {flag[now][i]=1;link(x[tmp.id],y[tmp.id],tmp);tot+=tmp.w;continue;}
s.split(x[tmp.id],y[tmp.id]);nows=s.sum[x[tmp.id]];nows.w>tmp.w&&(tot+=tmp.w-nows.w,flag[now][i]=1,g[now][i]=nows,cut(x[nows.id],y[nows.id],nows.id),link(x[tmp.id],y[tmp.id],tmp),0);
}
(l^r)?(find(l,m,l(now)),find(m+1,r,r(now)),0):(ans[l]=tot);
for(i=f[now].size()-1;i>=0;i--){
if(!flag[now][i]) continue;tmp=f[now][i];cut(x[tmp.id],y[tmp.id],tmp.id);
nows=g[now][i];tot-=tmp.w-nows.w;nows.id&&(link(x[nows.id],y[nows.id],nows),0);
}
}
int main(){
register int i;
freopen("1.in","r",stdin);
scanf("%d%d%d",&n,&m,&k);
for(i=1;i<=m;i++) last[i]=0,scanf("%d%d%d",&x[i],&y[i],&z[i]);
for(i=1;i<=k;i++) scanf("%d%d",&a,&b),get(last[a],i-1,(pai){a,z[a]}),z[a]=b,last[a]=i;
for(i=1;i<=m;i++) get(last[i],k,(pai){i,z[i]});find();
for(i=1;i<=k;i++) printf("%lld\n",ans[i]);
}
标签:int,luogu,void,P3206,fa,HNOI2010,now,id,nows 来源: https://www.cnblogs.com/275307894a/p/14532077.html