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

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
",ans);
        }else {
            id=rd(); z=rd(); id++;
            access(id+n); splay(id+n); l[id+n]=z; pushup(id+n);
        }
    }
}
原文地址:https://www.cnblogs.com/suika/p/9062687.html