UOJ_274_[清华集训2016]温暖会指引我们前行_LCT

时间:2020-11-28 18:31:29

UOJ_274_[清华集训2016]温暖会指引我们前行_LCT

任务描述:http://uoj.ac/problem/274


本题中的字典序不同在于空串的字典序最大。

并且题中要求排序后字典序最大

因此我们要求的路径一定是最大生成树上的路径。

于是变成了LCT模板题,动态维护最大生成树即可。

注意每次find可能会T,于是我又写了个并查集...

代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define RR register
inline char nc() {
static char buf[100000],*p1,*p2;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int rd() {
RR int x=0; RR char s=nc();
while(s<'0'||s>'9') s=nc();
while(s>='0'&&s<='9') x=(x<<3)+(x<<1)+s-'0',s=nc();
return x;
}
inline char rc() {
RR char s=nc();
while(s<'a'||s>'z') s=nc();
return s;
}
#define ls ch[p][0]
#define rs ch[p][1]
#define get(x) (ch[f[x]][1]==x)
#define isrt(x) (ch[f[x]][1]!=x&&ch[f[x]][0]!=x)
#define N 1000050
int ch[N][2],f[N],sum[N],mn[N],t[N],l[N],rev[N],n,m,xx[N],yy[N],fa[N];
char opt[10];
int find(int x) {
return fa[x]==x?x:fa[x]=find(fa[x]);
}
inline void pushup(int p) {
sum[p]=sum[ls]+sum[rs]+l[p];
mn[p]=p;
if(t[mn[ls]]<t[mn[p]]) mn[p]=mn[ls];
if(t[mn[rs]]<t[mn[p]]) mn[p]=mn[rs];
}
inline void pushdown(int p) {
if(rev[p]) {
swap(ch[ls][0],ch[ls][1]);
swap(ch[rs][0],ch[rs][1]);
rev[ls]^=1; rev[rs]^=1; rev[p]=0;
}
}
void rotate(int x) {
int y=f[x],z=f[y],k=get(x);
if(!isrt(y)) ch[z][ch[z][1]==y]=x;
ch[y][k]=ch[x][!k]; f[ch[y][k]]=y;
ch[x][!k]=y; f[y]=x; f[x]=z;
pushup(y); pushup(x);
}
void update(int p) {
if(!isrt(p)) update(f[p]);
pushdown(p);
}
void splay(int x) {
update(x);
for(int fa;fa=f[x],!isrt(x);rotate(x))
if(!isrt(fa))
rotate(get(fa)==get(x)?fa:x);
}
void access(int p) {
int t=0;
while(p) {
splay(p);
rs=t;
pushup(p);
t=p;
p=f[p];
}
}
void makeroot(int p) {
access(p); splay(p); swap(ls,rs); rev[p]^=1;
}
void link(int x,int p) {
makeroot(x); splay(p); f[x]=p;
}
void cut(int x,int p) {
makeroot(x); access(p); splay(p); f[x]=ls=0;
}
int querymin(int x,int p) {
makeroot(x); access(p); splay(p); return mn[p];
}
int qlen(int x,int p) {
makeroot(x); access(p); splay(p); return sum[p];
}
int main() {
n=rd(); m=rd();
int i,x,y,z,w,id;
for(i=0;i<=n;i++) t[i]=1<<30,mn[i]=i,fa[i]=i;
while(m--) {
opt[0]=rc();
if(opt[0]=='f') {
id=rd(); x=rd(); y=rd(); z=rd(); w=rd();
id++; x++; y++;
t[id+n]=z; l[id+n]=w; mn[id+n]=id+n; xx[id]=x; yy[id]=y;
int dx=find(x),dy=find(y);
if(dx==dy) {
int tmp=querymin(x,y);
if(t[tmp]>=z) continue;
cut(xx[tmp-n],tmp); cut(yy[tmp-n],tmp);
}else fa[dx]=dy;
link(id+n,x); link(id+n,y);
}else if(opt[0]=='m') {
x=rd(); y=rd(); x++; y++;
int ans=find(x)==find(y)?qlen(x,y):-1;
printf("%d\n",ans);
}else {
id=rd(); z=rd(); id++;
access(id+n); splay(id+n); l[id+n]=z; pushup(id+n);
}
}
}