看春晚不如写题...
第一次写维护边权的题,因为懒所以没学边权lct,写的是插入虚点存边权,但我猜两种写法的效率应该差不多
要求最低温度尽量高,所以只能走最高温度生成树上的边,用lct维护就行了
lct维护最大生成树,每加一条边$\left(x,y,T\right)$,如果两边不连通就直接连,如果连通且树上$x\rightarrow y$的最低温度$\geq T$,那么不用加边,否则删掉树上路径最低温的边,加入新边
个人觉得这种插入虚点维护边权的写法挺方便的
#include<stdio.h> int ch[400010][2],fa[400010],r[400010],t[400010],l[400010],mn[400010],mp[400010],s[400010]; #define ls ch[x][0] #define rs ch[x][1] void pushup(int x){ s[x]=s[ls]+s[rs]+l[x]; mn[x]=t[x]; mp[x]=x; if(ls&&mn[ls]<mn[x]){ mn[x]=mn[ls]; mp[x]=mp[ls]; } if(rs&&mn[rs]<mn[x]){ mn[x]=mn[rs]; mp[x]=mp[rs]; } } void swap(int&a,int&b){a^=b^=a^=b;} void rev(int x){ r[x]^=1; swap(ls,rs); } void pushdown(int x){ if(r[x]){ if(ls)rev(ls); if(rs)rev(rs); r[x]=0; } } bool isrt(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;} void gao(int x){ if(!isrt(x))gao(fa[x]); pushdown(x); } void rot(int x){ int y,z,f,B; y=fa[x]; z=fa[y]; f=(ch[y][0]==x); B=ch[x][f]; fa[x]=z; fa[y]=x; if(B)fa[B]=y; ch[x][f]=y; ch[y][f^1]=B; if(ch[z][0]==y)ch[z][0]=x; if(ch[z][1]==y)ch[z][1]=x; pushup(y); pushup(x); } void splay(int x){ int y,z; gao(x); while(!isrt(x)){ y=fa[x]; z=fa[y]; if(!isrt(y))rot((ch[z][0]==y&&ch[y][0]==x)||(ch[z][1]==y&&ch[y][1]==x)?y:x); rot(x); } } void access(int x){ int y=0; while(x){ splay(x); rs=y; pushup(x); y=x; x=fa[x]; } } void makert(int x){ access(x); splay(x); rev(x); } bool cn(int x,int y){ if(x==y)return 1; makert(x); access(y); splay(y); return fa[x]!=0; } void link(int x,int y){ makert(x); fa[x]=y; } void modify(int x,int v){ splay(x); l[x]=v; pushup(x); } int query(int x,int y){ if(!cn(x,y))return-1; makert(x); access(y); splay(y); return s[y]; } int querymin(int x,int y){ makert(x); access(y); splay(y); return mn[y]; } void cutmin(int x,int y){ makert(x); access(y); splay(y); x=mp[y]; splay(x); fa[ls]=fa[rs]=0; } void link(int id,int x,int y,int T,int L){ if(cn(x,y)){ if(querymin(x,y)>=T)return; cutmin(x,y); } mn[id]=t[id]=T; s[id]=l[id]=L; mp[id]=id; link(x,id); link(id,y); } int main(){ int n,m,i,u,v,t,l; char s[10]; scanf("%d%d",&n,&m); for(i=1;i<=n;i++)mn[i]=::t[i]=1000000000; while(m--){ scanf("%s",s); if(s[0]==‘f‘){ scanf("%d%d%d%d%d",&i,&u,&v,&t,&l); i++; u++; v++; link(i+n,u,v,t,l); } if(s[0]==‘m‘){ scanf("%d%d",&u,&v); u++; v++; printf("%d\n",query(u,v)); } if(s[0]==‘c‘){ scanf("%d%d",&i,&l); i++; modify(i+n,l); } } }
原文地址:https://www.cnblogs.com/jefflyy/p/8449773.html
时间: 2024-10-09 18:19:49