• LCT小结


    这里没有水表
    这几天连树剖和LCT都不会写了
    所以放下总结两篇

    LCT是一个通过链剖分和Splay的使用,在无根树上维护路径信息的有效算法
    其单次操作时间复杂度为O(logn),常数巨大

    Splay

    需要先学Splay(不会的我可不管),于是跳过Splay部分;

    主要结构和思路

    讲的就交给书予大佬了
    这里是一些无关紧要的压行

    il void access(int x){for(RG int y=0;x;y=x,x=fa[x])splay(x),s[1][x]=y,update(x);}
    il int findroot(int x){access(x);splay(x);while(s[0][x])x=s[0][x];return x;}
    il void makeroot(int x){access(x);splay(x);reverse(x);}
    il void link(int x,int y){makeroot(x);fa[x]=y;}
    il void split(int x,int y){makeroot(x);access(y);splay(y);}
    il void cut(int x,int y){split(x,y);fa[x]=s[0][y]=0;}
    

    注意一个Splay的reverse(区间翻转)操作
    节点上有懒标记的时候这个节点是不是已经被修改过了?
    是吧所以我们需要一个reverse的函数再pushdown

    il void reverse(int i){if(!i)return;swap(s[0][i],s[1][i]);rv[i]^=1;}
    il void pushdown(int i){
    if(rv[i]){reverse(s[0][i]);reverse(s[1][i]);rv[i]=0;}
    }
    

    注意:
    split请务必保证两个点联通
    cut请务必保证两个点直接相连
    link请务必保证两个点不联通
    不然出现玄学错误谁都救不了你了
    --摘自书予大佬

    #include<iostream>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #define RG register
    using namespace std;
    const int N=300010;
    
    int Orz,n,m,x,y;
    int s[2][N],fa[N],sum[N],val[N],rv[N];
    int cal[N],top;
    
    inline void update(int i){
        sum[i]=sum[s[0][i]]^sum[s[1][i]]^val[i];}
    inline void pushdown(int i){if(!rv[i])return;rv[i]^=1;rv[s[0][i]]^=1;rv[s[1][i]]^=1;swap(s[1][i],s[0][i]);}
    inline bool isroot(int i){
        return s[0][fa[i]]!=i&&s[1][fa[i]]!=i;}
    
    inline bool isr(int i){return s[1][fa[i]]==i;}
    inline void rot(int i){
        RG int j=fa[i],k=fa[j];
        RG bool b=isr(i);
        fa[i]=k;
        if(!isroot(j))s[isr(j)][k]=i;
        
        s[b][j]=s[!b][i];
        if(s[!b][i])fa[s[!b][i]]=j;
        
        s[!b][i]=j;fa[j]=i;
        update(j);
    }
    
    inline void splay(int i){
        cal[++top]=i;
        for(RG int x=i;!isroot(x);x=fa[x])cal[++top]=fa[x];//
        while(top)pushdown(cal[top--]);//
        for(RG int j=fa[i];!isroot(i);rot(i),j=fa[i])
            if(!isroot(j))isr(i)^isr(j)?rot(i):rot(j);
        update(i);
    }
    
    inline void access(int x){for(RG int y=0;x;y=x,x=fa[x])splay(x),s[1][x]=y,update(x);}
    inline void makeroot(int x){access(x);splay(x);rv[x]^=1;}
    inline int findroot(int x){access(x);splay(x);while(s[0][x])x=s[0][x];return x;}
    inline void split(int x,int y){makeroot(x);access(y);splay(y);}//
    inline void cut(int x,int y){split(x,y);fa[x]=s[0][y]=0;}//
    inline void link(int x,int y){makeroot(x);fa[x]=y;}
    
    inline void print(int i){
        if(s[0][i])print(s[0][i]);
        printf("%d ",val[i]);
        if(s[1][i])print(s[1][i]);
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for(RG int i=1;i<=n;i++)scanf("%d",&val[i]);
        while(m--){
            scanf("%d%d%d",&Orz,&x,&y);
            if(!Orz){split(x,y);printf("%d
    ",sum[y]);}
            if(Orz==1)if(findroot(x)!=findroot(y))link(x,y);//
            if(Orz==2)if(findroot(x)==findroot(y))cut(x,y);
            if(Orz==3){access(x);splay(x);val[x]=y;update(x);}
        }
        return 0;
    }
    

    [luoguP1501] [国家集训队]Tree II

    这里是带修改的LCT

    #include<bits/stdc++.h>
    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<iomanip>
    #include<cstring>
    #include<complex>
    #include<vector>
    #include<cstdio>
    #include<string>
    #include<bitset>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<map>
    #include<set>
    #define mp make_pair
    #define pb push_back
    #define RG register
    #define il inline
    #define isr(i) (s[1][fa[i]]==i)
    #define isroot(i) (s[0][fa[i]]!=i&&s[1][fa[i]]!=i)
    using namespace std;
    typedef unsigned long long ull;
    typedef vector<int>VI;
    typedef long long ll;
    typedef double dd;
    const dd eps=1e-10;
    const int mod=51061;
    const int N=100010;
    il ll read(){
        RG ll data=0,w=1;RG char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')w=-1,ch=getchar();
        while(ch<='9'&&ch>='0')data=data*10+ch-48,ch=getchar();
        return data*w;
    }
    
    il void file(){
        freopen("a.in","r",stdin);
        freopen("a.out","w",stdout);
    }
    
    ll n,q;char c;
    ll fa[N],s[2][N],sz[N],val[N],rv[N],sum[N],add[N],times[N],cal[N],top;
    il void update(int i){
        sum[i]=(sum[s[0][i]]+sum[s[1][i]]+val[i])%mod;
        sz[i]=sz[s[0][i]]+sz[s[1][i]]+1;
    }
    il void reverse(int i){
        if(!i)return;swap(s[0][i],s[1][i]);rv[i]^=1;
    }
    il void modify(int i,int t,int a){
        sum[i]=(sum[i]*t+a*sz[i])%mod;
        val[i]=(val[i]*t+a)%mod;
        times[i]=times[i]*t%mod;
        add[i]=(add[i]*t+a)%mod;
    }
    il void pushdown(int i){
        if(rv[i]){reverse(s[0][i]);reverse(s[1][i]);rv[i]=0;}
        if(add[i]||times[i]!=1){
            if(s[0][i])modify(s[0][i],times[i],add[i]);
            if(s[1][i])modify(s[1][i],times[i],add[i]);
            add[i]=0;times[i]=1;
        }
    }
    
    il void rot(int i){
        RG int j=fa[i],k=fa[j];
        RG bool b=isr(i);
        if(!isroot(j))s[isr(j)][k]=i;fa[i]=k;
        if(s[!b][i])fa[s[!b][i]]=j;s[b][j]=s[!b][i];
        s[!b][i]=j;fa[j]=i;
        update(j);
    }
    il void splay(int i){
        cal[++top]=i;
        for(RG int x=i;!isroot(x);x=fa[x])cal[++top]=fa[x];
        while(top)pushdown(cal[top--]);
        for(RG int j=fa[i];!isroot(i);rot(i),j=fa[i])
            if(!isroot(j))(isr(i)^isr(j))?rot(i):rot(j);
        update(i);
    }
    
    il void access(int x){for(RG int y=0;x;y=x,x=fa[x])splay(x),s[1][x]=y,update(x);}
    il int findroot(int x){access(x);splay(x);while(s[0][x])x=s[0][x];return x;}
    il void makeroot(int x){access(x);splay(x);reverse(x);}
    il void link(int x,int y){makeroot(x);fa[x]=y;}
    il void split(int x,int y){makeroot(x);access(y);splay(y);}
    il void cut(int x,int y){split(x,y);fa[x]=s[0][y]=0;}
    
    il void modify_add(){
        RG int u=read(),v=read(),c=read()%mod;
        split(u,v);modify(v,1,c);
    }
    il void update_line(){
        RG int u1=read(),v1=read(),u2=read(),v2=read();
        cut(u1,v1);link(u2,v2);
    }
    il void modify_times(){
        RG int u=read(),v=read(),c=read()%mod;
        split(u,v);modify(v,c,0);
    }
    il void query(){
        RG int u=read(),v=read();split(u,v);
        printf("%lld
    ",sum[v]);
    }
    
    int main()
    {
        n=read();q=read();
        for(RG int i=1;i<=n;i++)modify(i,1,1),sz[i]=1;
        for(RG int i=1,u,v;i<n;i++){
            u=read();v=read();link(u,v);
        }
        for(RG int i=1;i<=q;i++){
            c=0;while(c!='+'&&c!='-'&&c!='*'&&c!='/')c=getchar();
            if(c=='+')modify_add();
            if(c=='-')update_line();
            if(c=='*')modify_times();
            if(c=='/')query();
        }
        return 0;
    }
    

    [luoguP4172] [WC2006]水管局长

    其实离线+倒序处理询问就变成魔法森林(动态维护最小生成树)了

    #include<bits/stdc++.h>
    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<iomanip>
    #include<cstring>
    #include<complex>
    #include<vector>
    #include<cstdio>
    #include<string>
    #include<bitset>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<map>
    #include<set>
    #define mp make_pair
    #define pb push_back
    #define RG register
    #define il inline
    #define isr(i) (s[1][fa[i]]==i)
    #define isroot(i) (s[0][fa[i]]!=i&&s[1][fa[i]]!=i)
    using namespace std;
    typedef unsigned long long ull;
    typedef vector<int>VI;
    typedef long long ll;
    typedef double dd;
    const dd eps=1e-10;
    const int N=100010;
    il ll read(){
        RG ll data=0,w=1;RG char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')w=-1,ch=getchar();
        while(ch<='9'&&ch>='0')data=data*10+ch-48,ch=getchar();
        return data*w;
    }
    
    il void file(){
        freopen("a.in","r",stdin);
        freopen("a.out","w",stdout);
    }
    
    int n,m,q,tot=1;
    int fa[N<<1],s[2][N<<1],val[N<<1],rv[N<<1],mx[N<<1],pmx[N<<1];
    il void update(int i){
        mx[i]=val[i];pmx[i]=i;
        if(s[0][i]&&mx[s[0][i]]>mx[i]){
            mx[i]=mx[s[0][i]];pmx[i]=pmx[s[0][i]];
        }
        if(s[1][i]&&mx[s[1][i]]>mx[i]){
            mx[i]=mx[s[1][i]];pmx[i]=pmx[s[1][i]];
        }
    }
    il void reverse(int i){swap(s[0][i],s[1][i]);rv[i]^=1;}
    il void pushdown(int i){
        if(!rv[i])return;
        reverse(s[0][i]);reverse(s[1][i]);
        rv[i]=0;
    }
    
    il void rot(int i){
        RG int j=fa[i],k=fa[j];
        RG bool b=isr(i);
        if(!isroot(j))s[isr(j)][k]=i;fa[i]=k;
        if(s[!b][i])fa[s[!b][i]]=j;s[b][j]=s[!b][i];
        s[!b][i]=j;fa[j]=i;
        update(j);
    }
    int cal[N<<1],top;
    il void splay(int i){
        cal[++top]=i;
        for(RG int x=i;!isroot(x);x=fa[x])cal[++top]=fa[x];
        while(top)pushdown(cal[top--]);
        for(RG int j=fa[i];!isroot(i);rot(i),j=fa[i])
            if(!isroot(j))(isr(i)^isr(j))?rot(i):rot(j);
        update(i);
    }
    
    int f[N<<1];
    il void access(int x){for(RG int y=0;x;y=x,x=fa[x])splay(x),s[1][x]=y,update(x);}
    il void makeroot(int x){access(x);splay(x);reverse(x);}
    il int find(int x){return f[x]?f[x]=find(f[x]):x;}
    il void split(int x,int y){makeroot(x);access(y);splay(y);}
    il void link(int x,int y){
        makeroot(x);fa[x]=y;
    }
    il void cut(int x,int y){
        split(x,y);fa[x]=s[0][y]=0;
    }
    
    int l[N],r[N],cnt;
    il int query(int u,int v){
        split(u,v);
        return pmx[v];
    }
    il void add(int u,int v,int w){
        if(find(u)!=find(v)){
            cnt++;val[n+cnt]=w;l[cnt]=u;r[cnt]=v;
            link(u,n+cnt);link(n+cnt,v);
            f[find(u)]=find(v);
        }
        else{
            RG int i=query(u,v);
            if(val[i]>w){
                cut(i,l[i-n]);cut(i,r[i-n]);
                l[i-n]=u;r[i-n]=v;val[i]=w;
                link(u,i);link(i,v);
            }
        }
    }
    
    struct edge{
        int u,v,t,id;
        bool operator <(const edge b)const{
            return (u==b.u)?v<b.v:u<b.u;
        }
    }E[N];
    bool cmp(edge a,edge b){return a.id>b.id;}
    struct qry{int u,v,ans;}Q[N];
    int main()
    {
        n=read();m=read();q=read();
        for(RG int i=1,x,y,w;i<=m;i++){
            x=read();y=read();w=read();if(x>y)swap(x,y);
            E[i]=(edge){x,y,w,0};
        }
        
        sort(E+1,E+m+1);
        for(RG int i=1,k,x,y;i<=q;i++){
            k=read();x=read();y=read();if(x>y)swap(x,y);
            if(k==1)Q[++tot]=(qry){x,y,0};
            if(k==2){
                E[lower_bound(E+1,E+m+1,(edge){x,y,0,0})-E].id=tot;
            }
        }
        for(RG int i=1;i<=m;i++)if(!E[i].id)E[i].id=tot;
        
        sort(E+1,E+m+1,cmp);
        for(RG int i=tot,l=1;i>=2;i--){
            while(E[l].id==i&&l<=m){add(E[l].u,E[l].v,E[l].t);l++;}
            Q[i].ans=val[query(Q[i].u,Q[i].v)];
        }
        for(RG int i=2;i<=tot;i++)printf("%d
    ",Q[i].ans);
        return 0;
    }
    
  • 相关阅读:
    MySQL案例:一次单核CPU占用过高问题的处理
    编写你的第一个Django应用
    ks.cfg文件相关
    Kickstart部署多系统
    Kickstart部署之FTP架构
    Kickstart部署之HTTP架构
    Kickstart部署之NFS架构
    Kickstart无人值守原理及简介
    Linux下面Oracle实列实如何登录的
    welogic的受管理服务器无法启动
  • 原文地址:https://www.cnblogs.com/cjfdf/p/8470913.html
Copyright © 2020-2023  润新知