@ysner
2018-09-18T03:01:50.000000Z
字数 2319
阅读 2155
LCT
既然题目中把字典序的定义倒过来了,就说明要我们动态维护最大生成树(温度)。
显然只有能胜任这种操作。
鉴于只能维护点权,所以我们对每条边新建一个点,点权为边长,然后新点与两端点相连。
然后同时维护路径长度的和即可。
注意修改点信息时要那个点。
#include<iostream>#include<cstring>#include<cmath>#include<cstdio>#include<cstdlib>#include<algorithm>#define ll long long#define re register#define il inline#define ls t[0][x]#define rs t[1][x]#define fp(i,a,b) for(re int i=a;i<=b;i++)#define fq(i,a,b) for(re int i=a;i>=b;i--)using namespace std;const int N=5e5+100;int n,m,f[N],tag[N],t[2][N],sta[N],top,val[N],tem[N],p[N];ll s[N];struct dat{int u,v;}a[N];il ll gi(){re ll x=0,t=1;re char ch=getchar();while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();if(ch=='-') t=-1,ch=getchar();while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();return x*t;}il void upd(re int x){s[x]=s[ls]+s[rs]+val[x];p[x]=x;if(ls&&tem[p[ls]]<tem[p[x]]) p[x]=p[ls];if(rs&&tem[p[rs]]<tem[p[x]]) p[x]=p[rs];}il int son(re int x){return x==t[1][f[x]];}il int isrt(re int x){return x!=t[0][f[x]]&&x!=t[1][f[x]];}il void rev(re int x){if(!x) return;swap(ls,rs);tag[x]^=1;}il void pushdown(re int x){if(!tag[x]) return;rev(ls);rev(rs);tag[x]=0;}il void rotate(re int x){re int y=f[x],z=f[y],c=son(x);t[c][y]=t[c^1][x];if(t[c][y]) f[t[c][y]]=y;f[x]=z;if(!isrt(y)) t[son(y)][z]=x;t[c^1][x]=y;f[y]=x;upd(y);}il void splay(re int x){sta[top=1]=x;for(re int i=x;!isrt(i);i=f[i]) sta[++top]=f[i];while(top) pushdown(sta[top--]);for(re int y=f[x];!isrt(x);rotate(x),y=f[x])if(!isrt(y)) son(x)^son(y)?rotate(x):rotate(y);upd(x);}il void access(re int x){for(re int y=0;x;y=x,x=f[x]) splay(x),rs=y,upd(x);}il void makert(re int x){access(x);splay(x);rev(x);}il int findrt(re int x){access(x);splay(x);while(ls) x=ls;splay(x);return x;}il void split(re int x,re int y){makert(x);access(y);splay(y);}il void link(re int x,re int y){makert(x);f[x]=y;}il void cut(re int x,re int y){split(x,y);t[0][y]=f[x]=0;upd(y);}il int Query(re int x,re int y){split(x,y);return s[y];}int main(){n=gi();m=gi();fp(i,1,n) tem[i]=2e9;fp(i,1,m){re char op[10];scanf("%s",op);if(op[0]=='f'){re int id=gi()+n+1,u=gi()+1,v=gi()+1;tem[id]=gi(),val[id]=gi();a[id]=(dat){u,v};if(findrt(u)^findrt(v)) link(u,id),link(v,id);else{split(u,v);re int pos=p[v];if(tem[pos]<tem[id]){cut(a[pos].u,pos);cut(a[pos].v,pos);link(u,id);link(v,id);}}}if(op[0]=='m'){re int u=gi()+1,v=gi()+1;if(findrt(u)^findrt(v)) {puts("-1");continue;}printf("%d\n",Query(u,v));}if(op[0]=='c'){re int id=gi()+n+1,w=gi();val[id]=w;splay(id);}}return 0;}
