zoukankan      html  css  js  c++  java
  • 【Learning】倍增求LCA题目汇总

    这里是我倍增的练习记录,大多都是水题……也有一些混合了其它算法的。= = silly……顺序可能有些错乱,并不是按照难度来排的。
    T1 hdu3710 倍增+树剖
    这里写图片描述

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    using namespace std;
    const int N=20005,M=100005,inf=2139062143;
    int t,n,m,u,v,d,f,ns,rt,cnt,idx,head[N],to[N*2],nxt[N*2];
    int dep[N],fa[N][20],siz[N],son[N],dfn[N],pos[N],top[N];
    int minn[N],minv[N*4],tag[N*4];
    bool use[M];
    int s,mst,smst,pa[N],w[N],sont[N],num[N];
    struct edge{
        int u,v,d;
        bool operator < (const edge &x)const{
            return d<x.d;
        }
    }e[M];
    vector<edge> link[N],edges;
    void init(){
        smst=idx=cnt=rt=0;
        memset(use,0,sizeof(use));
        memset(head,0,sizeof(head));
        memset(dep,0,sizeof(dep));
        memset(fa,0,sizeof(fa));
        memset(son,0,sizeof(son));
        memset(sont,0,sizeof(sont));
        memset(w,0,sizeof(w));
        memset(minv,127,sizeof(minv));
        memset(tag,127,sizeof(tag));
        for(int i=1;i<=n;i++){
            pa[i]=i;
            link[i].clear();
        }
    }
    void adde(int u,int v){
        to[++cnt]=v;
        nxt[cnt]=head[u];
        head[u]=cnt;
    }
    int find(int u){
        return u==pa[u]?u:pa[u]=find(pa[u]);
    }
    void dfs(int u){
        for(int i=1;(1<<i)<=dep[u];i++){
            fa[u][i]=fa[fa[u][i-1]][i-1];
        }
        siz[u]=1;
        int v;
        for(int i=head[u];i;i=nxt[i]){
            v=to[i];
            if(v!=fa[u][0]){
                fa[v][0]=u;
                dep[v]=dep[u]+1;
                num[v]=++sont[u];
                dfs(v);
                siz[u]+=siz[v];
                if(!son[u]||siz[son[u]]<siz[v]){
                    son[u]=v;
                }
            }
        }
    }
    void dfs(int u,int tp){
        dfn[u]=++idx;
        pos[idx]=u;
        top[u]=tp;
        if(son[u]){
            dfs(son[u],tp);
        }
        int v;
        for(int i=head[u];i;i=nxt[i]){
            v=to[i];
            if(v!=fa[u][0]&&v!=son[u]){
                dfs(v,v);
            }
        }
    }
    void pushdown(int o){
        minv[o*2]=min(minv[o*2],tag[o]);
        minv[o*2+1]=min(minv[o*2+1],tag[o]);
        tag[o*2]=min(tag[o*2],tag[o]);
        tag[o*2+1]=min(tag[o*2+1],tag[o]);
        tag[o]=inf;
    }
    void upd(int o,int l,int r,int L,int R,int x){
        if(L<=l&&R>=r){
            minv[o]=min(minv[o],x);
            tag[o]=min(tag[o],x);
            return;
        }
        if(tag[o]!=inf){
            pushdown(o);
        }
        int mid=(l+r)/2;
        if(L<=mid){
            upd(o*2,l,mid,L,R,x);
        }
        if(R>mid){
            upd(o*2+1,mid+1,r,L,R,x);
        }
        minv[o]=min(minv[o*2],minv[o*2+1]);
    }
    void update(int u,int v,int x){
        while(top[u]!=top[v]){
            upd(1,1,n,dfn[top[u]],dfn[u],x);
            u=fa[top[u]][0];
        }
        upd(1,1,n,dfn[v],dfn[u],x);
    }
    void getmin(int o,int l,int r){
        if(l==r){
            minn[pos[l]]=minv[o];
            return;
        }
        if(tag[o]!=inf){
            pushdown(o);
        }
        int mid=(l+r)/2;
        getmin(o*2,l,mid);
        getmin(o*2+1,mid+1,r);
    }
    void work(edge &e){
        int u=e.u,v=e.v,d;
        d=dep[u]-dep[v];
        for(int i=0;(1<<i)<=d;i++){
            if(d&(1<<i)){
                u=fa[u][i];
            }
        }
        if(u==v){
            u=e.u;
            d=dep[u]-dep[v]-2;
            if(d<0){
                return;
            }
            for(int i=0;(1<<i)<=d;i++){
                if(d&(1<<i)){
                    u=fa[u][i];
                }
            }
            update(e.u,u,e.d);
            return;
        }
        int tmpu=u,tmpv=v;
        for(int i=15;i>=0;i--){
            if(fa[tmpu][i]!=fa[tmpv][i]){
                tmpu=fa[tmpu][i];
                tmpv=fa[tmpv][i];
            }
        }
        link[fa[tmpu][0]].push_back((edge){tmpu,tmpv,e.d});
        d=dep[e.u]-dep[tmpu]-1;
        if(d>=0){
            u=e.u;
            for(int i=0;(1<<i)<=d;i++){
                if(d&(1<<i)){
                    u=fa[u][i];
                }
            }
            update(e.u,u,e.d);
        }
        d=dep[e.v]-dep[tmpv]-1;
        if(d>=0){
            v=e.v;
            for(int i=0;(1<<i)<=d;i++){
                if(d&(1<<i)){
                    v=fa[v][i];
                }
            }
            update(e.v,v,e.d);
        }
    }
    int main(){
        scanf("%d",&t);
        while(t--){
            scanf("%d%d",&n,&m);
            init();
            for(int i=1;i<=m;i++){
                scanf("%d%d%d%d",&e[i].u,&e[i].v,&d,&f);
                e[i].d=d*(1-f);
            }
            sort(e+1,e+m+1);
            ns=0;
            for(int i=1;i<=m&&ns<n-1;i++){
                u=find(e[i].u),v=find(e[i].v);
                if(u!=v){
                    use[i]=true;
                    pa[v]=u;
                    ns++;
                    adde(e[i].u,e[i].v);
                    adde(e[i].v,e[i].u);
                    w[e[i].u]+=e[i].d;
                    w[e[i].v]+=e[i].d;
                    smst+=e[i].d;
                    if(!rt){
                        rt=e[i].u;
                    }
                }
            }
            dfs(rt);
            dfs(rt,rt);
            for(int i=1;i<=m;i++){
                if(!use[i]){
                    if(dep[e[i].u]<dep[e[i].v]){
                        swap(e[i].u,e[i].v);
                    }
                    work(e[i]);
                }
            }
            getmin(1,1,n);
            for(int i=1;i<=n;i++){
                edges.clear();
                s=sont[i];
                if(fa[i][0]){
                    s++;
                    for(int j=head[i];j;j=nxt[j]){
                        v=to[j];
                        if(v!=fa[i][0]&&minn[v]!=inf){
                            edges.push_back((edge){num[v],s,minn[v]});
                        }
                    }
                }
                for(int j=0;j<link[i].size();j++){
                    edges.push_back((edge){num[link[i][j].u],num[link[i][j].v],link[i][j].d});
                }
                sort(edges.begin(),edges.end());
                mst=0;
                for(int j=1;j<=s;j++){
                    pa[j]=j;
                }
                ns=0;
                for(int j=0;j<edges.size()&&ns<s-1;j++){
                    u=find(edges[j].u),v=find(edges[j].v);
                    if(u!=v){
                        pa[v]=u;
                        ns++;
                        mst+=edges[j].d;
                    }
                }
                if(ns<s-1){
                    puts("inf");
                }else{
                    printf("%d
    ",smst-w[i]+mst);
                }
            }
        }
        return 0;
    }

    T2 luogu3379 模板题
    这里写图片描述

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int n,m,root,cnt,u,v,head[500005],to[1000005],nxt[1000005],dep[500005],fa[500005][21];
    void adde(int u,int v){
        to[++cnt]=v;
        nxt[cnt]=head[u];
        head[u]=cnt;
    }
    void dfs(int u){
        for(int i=1;(1<<i)<=dep[u];i++){
            fa[u][i]=fa[fa[u][i-1]][i-1];
        }
        int v;
        for(int i=head[u];i;i=nxt[i]){
            v=to[i];
            if(v!=fa[u][0]){
                fa[v][0]=u;
                dep[v]=dep[u]+1;
                dfs(v);
            }
        }
    }
    int lca(int u,int v){
        if(dep[u]<dep[v]){
            swap(u,v);
        }
        int d=dep[u]-dep[v];
        for(int i=0;(1<<i)<=d;i++){
            if(d&(1<<i)){
                u=fa[u][i];
            }
        }
        if(u==v){
            return u;
        }
        for(int i=20;i>=0;i--){
            if(fa[u][i]!=fa[v][i]){
                u=fa[u][i];
                v=fa[v][i];
            }
        }
        return fa[u][0];
    }
    int main(){
        scanf("%d%d%d",&n,&m,&root);
        for(int i=1;i<n;i++){
            scanf("%d%d",&u,&v);
            adde(u,v);
            adde(v,u);
        }
        dfs(root);
        while(m--){
            scanf("%d%d",&u,&v);
            printf("%d
    ",lca(u,v));
        }
        return 0;
    }

    T3 zoj3195 模板题
    这里写图片描述

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int n,q,cnt,u,v,d,head[50005],to[100005],nxt[100005],dep[50005],dis[50005],dd[100005],fa[50005][21];
    bool flag=false; 
    void adde(int u,int v,int d){
        to[++cnt]=v;
        nxt[cnt]=head[u];
        dd[cnt]=d;
        head[u]=cnt;
    }
    void dfs(int u){
        for(int i=1;(1<<i)<=dep[u];i++){
            fa[u][i]=fa[fa[u][i-1]][i-1];
        }
        int v;
        for(int i=head[u];i;i=nxt[i]){
            v=to[i];
            if(v!=fa[u][0]){
                fa[v][0]=u;
                dep[v]=dep[u]+1;
                dis[v]=dis[u]+dd[i];
                dfs(v);
            }
        }
    }
    int lca(int u,int v){
        if(dep[u]<dep[v]){
            swap(u,v);
        }
        int d=dep[u]-dep[v];
        for(int i=0;(1<<i)<=d;i++){
            if(d&(1<<i)){
                u=fa[u][i];
            }
        }
        if(u==v){
            return u;
        }
        for(int i=20;i>=0;i--){
            if(fa[u][i]!=fa[v][i]){
                u=fa[u][i];
                v=fa[v][i];
            }
        }
        return fa[u][0];
    }
    int main(){
        while(~scanf("%d",&n)){
            if(!flag){
                flag=true;
            }else{
                puts("");
            }
            cnt=0;
            memset(head,0,sizeof(head));
            memset(dep,0,sizeof(dep));
            memset(fa,0,sizeof(fa));
            memset(dis,0,sizeof(dis)); 
            for(int i=1;i<n;i++){
                scanf("%d%d%d",&u,&v,&d);
                u++,v++;
                adde(u,v,d);
                adde(v,u,d);
            }
            dfs(1);
            scanf("%d",&q);
            for(int i=1;i<=q;i++){
                scanf("%d%d%d",&u,&v,&d);
                u++,v++,d++;
                printf("%d
    ",dis[u]+dis[v]+dis[d]-dis[lca(u,v)]-dis[lca(u,d)]-dis[lca(v,d)]);
            }
        }
        return 0;
    }

    T4 bzoj2588 主席树+树上差分+倍增lca
    这里写图片描述

    #include<cstdio>
    #include<vector>
    #include<algorithm>
    using namespace std;
    const int N=100005;
    int n,m,x,y,k,lca,lastans=0,tot=0,cnt=0,a[N],head[N],nxt[N*2],to[N*2],root[N],dep[N],fa[N][20];
    vector<int> v;
    struct Node
    {
        int l,r,sum;
        Node(){sum=0;}
    }node[N*40];
    int getId(int x)
    {
        return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
    }
    void adde(int u,int v)
    {
        to[++tot]=v;
        nxt[tot]=head[u];
        head[u]=tot;
    }
    void update(int l,int r,int &x,int y,int pos)
    {
        node[x=++cnt]=node[y];
        node[x].sum++;
        if(l==r) return;
        int mid=(l+r)/2;
        if(pos<=mid) update(l,mid,node[x].l,node[y].l,pos);
        else update(mid+1,r,node[x].r,node[y].r,pos);
    }
    int query(int l,int r,int a,int b,int c,int d,int k)
    {
        if(l==r) return l;
        int mid=(l+r)/2,sum=node[node[a].l].sum+node[node[b].l].sum-node[node[c].l].sum-node[node[d].l].sum;
        if(k<=sum) return query(l,mid,node[a].l,node[b].l,node[c].l,node[d].l,k);
        else return query(mid+1,r,node[a].r,node[b].r,node[c].r,node[d].r,k-sum);
    }
    void dfs(int pre,int u,int d)
    {
        fa[u][0]=pre;
        dep[u]=d;
        for(int i=1;(1<<i)<=d;i++)
            fa[u][i]=fa[fa[u][i-1]][i-1];
        update(1,n,root[u],root[pre],getId(a[u]));
        for(int i=head[u];i;i=nxt[i])
            if(to[i]^pre)
                dfs(u,to[i],d+1);
    }
    int LCA(int u,int v)
    {
        if(dep[u]>dep[v]) swap(u,v);
        int d=dep[v]-dep[u];
        for(int i=0;(1<<i)<=d;i++)
            if((1<<i)&d) v=fa[v][i];
        if(u!=v)
        {
            for(int i=16;i>=0;i--)
                if(fa[u][i]!=fa[v][i])
                {
                    u=fa[u][i];
                    v=fa[v][i];
                }
            u=fa[u][0];
        }
        return u;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            v.push_back(a[i]);
        }
        sort(v.begin(),v.end());
        v.erase(unique(v.begin(),v.end()),v.end());
        for(int i=1;i<n;i++)
        {
            scanf("%d%d",&x,&y);
            adde(x,y);
            adde(y,x);
        }
        dfs(0,1,1);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&x,&y,&k);
            x^=lastans;
            lca=LCA(x,y);
            lastans=v[query(1,n,root[x],root[y],root[lca],root[fa[lca][0]],k)-1];
            printf("%d",lastans);
            if(i^m) putchar('
    ');
        }
        return 0;
    }

    T5 bzoj1787&&bzoj1832 模版题
    这里写图片描述
    这里写图片描述

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int t,n,q,cnt,u,v,d,t1,t2,t3,p,head[500005],to[1000005],nxt[1000005],dep[500005],fa[500005][21];
    void adde(int u,int v){
        to[++cnt]=v;
        nxt[cnt]=head[u];
        head[u]=cnt;
    }
    void dfs(int u){
        for(int i=1;(1<<i)<=dep[u];i++){
            fa[u][i]=fa[fa[u][i-1]][i-1];
        }
        int v;
        for(int i=head[u];i;i=nxt[i]){
            v=to[i];
            if(v!=fa[u][0]){
                fa[v][0]=u;
                dep[v]=dep[u]+1;
                dfs(v);
            }
        }
    }
    int lca(int u,int v){
        if(dep[u]<dep[v]){
            swap(u,v);
        }
        int d=dep[u]-dep[v];
        for(int i=0;(1<<i)<=d;i++){
            if(d&(1<<i)){
                u=fa[u][i];
            }
        }
        if(u==v){
            return u;
        }
        for(int i=20;i>=0;i--){
            if(fa[u][i]!=fa[v][i]){
                u=fa[u][i];
                v=fa[v][i];
            }
        }
        return fa[u][0];
    }
    int dis(int u,int v){
        return dep[u]+dep[v]-2*dep[lca(u,v)]; 
    }
    int main(){
        scanf("%d%d",&n,&q);
        for(int i=1;i<n;i++){
            scanf("%d%d",&u,&v);
            adde(u,v);
            adde(v,u);
        }
        dfs(1);
        for(int i=1;i<=q;i++){
            scanf("%d%d%d",&u,&v,&d);
            t1=lca(u,v),t2=lca(u,d),t3=lca(v,d);
            if(t1==t2){
                p=t3;
            }
            else if(t1==t3){
                p=t2;
            }
            else{
                p=t1;
            }
            printf("%d %d
    ",p,dis(u,p)+dis(v,p)+dis(d,p));
        }
        return 0;
    }

    T6 hdu2586 模版题
    这里写图片描述

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int t,n,q,cnt,u,v,d,head[40005],to[80005],nxt[80005],dep[40005],dis[40005],dd[800005],fa[40005][21];
    void adde(int u,int v,int d){
        to[++cnt]=v;
        nxt[cnt]=head[u];
        dd[cnt]=d;
        head[u]=cnt;
    }
    void dfs(int u){
        for(int i=1;(1<<i)<=dep[u];i++){
            fa[u][i]=fa[fa[u][i-1]][i-1];
        }
        int v;
        for(int i=head[u];i;i=nxt[i]){
            v=to[i];
            if(v!=fa[u][0]){
                fa[v][0]=u;
                dep[v]=dep[u]+1;
                dis[v]=dis[u]+dd[i];
                dfs(v);
            }
        }
    }
    int lca(int u,int v){
        if(dep[u]<dep[v]){
            swap(u,v);
        }
        int d=dep[u]-dep[v];
        for(int i=0;(1<<i)<=d;i++){
            if(d&(1<<i)){
                u=fa[u][i];
            }
        }
        if(u==v){
            return u;
        }
        for(int i=20;i>=0;i--){
            if(fa[u][i]!=fa[v][i]){
                u=fa[u][i];
                v=fa[v][i];
            }
        }
        return fa[u][0];
    }
    int main(){
        scanf("%d",&t);
        while(t--){
            scanf("%d%d",&n,&q);
            cnt=0;
            memset(head,0,sizeof(head));
            memset(dep,0,sizeof(dep));
            memset(fa,0,sizeof(fa));
            memset(dis,0,sizeof(dis)); 
            for(int i=1;i<n;i++){
                scanf("%d%d%d",&u,&v,&d);
                adde(u,v,d);
                adde(v,u,d);
            }
            dfs(1);
            for(int i=1;i<=q;i++){
                scanf("%d%d",&u,&v);
                printf("%d
    ",dis[u]+dis[v]-2*dis[lca(u,v)]);
            }
        }
        return 0;
    }

    T7 poj1330 模版题
    这里写图片描述

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int t,n,cnt,u,v,head[10005],to[10005],nxt[10005],dep[10005],fa[10005][21];
    bool ck[10005];
    void adde(int u,int v){
        to[++cnt]=v;
        nxt[cnt]=head[u];
        head[u]=cnt;
    }
    void dfs(int u){
        for(int i=1;(1<<i)<=dep[u];i++){
            fa[u][i]=fa[fa[u][i-1]][i-1];
        }
        int v;
        for(int i=head[u];i;i=nxt[i]){
            v=to[i];
            fa[v][0]=u;
            dep[v]=dep[u]+1;
            dfs(v);
        }
    }
    int lca(int u,int v){
        if(dep[u]<dep[v]){
            swap(u,v);
        }
        int d=dep[u]-dep[v];
        for(int i=0;(1<<i)<=d;i++){
            if(d&(1<<i)){
                u=fa[u][i];
            }
        }
        if(u==v){
            return u;
        }
        for(int i=20;i>=0;i--){
            if(fa[u][i]!=fa[v][i]){
                u=fa[u][i];
                v=fa[v][i];
            }
        }
        return fa[u][0];
    }
    int main(){
        scanf("%d",&t);
        while(t--){
            scanf("%d",&n);
            cnt=0;
            memset(head,0,sizeof(head));
            memset(dep,0,sizeof(dep));
            memset(fa,0,sizeof(fa));
            memset(ck,0,sizeof(ck));
            for(int i=1;i<n;i++){
                scanf("%d%d",&u,&v);
                adde(u,v);
                ck[v]=true;
            }
            for(int i=1;i<=n;i++){
                if(!ck[i]){
                    dfs(i);
                    break;
                }
            }
            scanf("%d%d",&u,&v);
            printf("%d
    ",lca(u,v));
        }
        return 0;
    }

    T8 gdgzoi2232祖孙询问 模版题
    这里写图片描述

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int t,n,m,cnt,u,v,tmp,rt,head[40005],to[80005],nxt[80005],dep[40005],fa[40005][21];
    void adde(int u,int v){
        to[++cnt]=v;
        nxt[cnt]=head[u];
        head[u]=cnt;
    }
    void dfs(int u){
        for(int i=1;(1<<i)<=dep[u];i++){
            fa[u][i]=fa[fa[u][i-1]][i-1];
        }
        int v;
        for(int i=head[u];i;i=nxt[i]){
            v=to[i];
            if(v!=fa[u][0]){
                fa[v][0]=u;
                dep[v]=dep[u]+1;
                dfs(v);
            }
        }
    }
    int lca(int u,int v){
        if(dep[u]<dep[v]){
            swap(u,v);
        }
        int d=dep[u]-dep[v];
        for(int i=0;(1<<i)<=d;i++){
            if(d&(1<<i)){
                u=fa[u][i];
            }
        }
        if(u==v){
            return u;
        }
        for(int i=20;i>=0;i--){
            if(fa[u][i]!=fa[v][i]){
                u=fa[u][i];
                v=fa[v][i];
            }
        }
        return fa[u][0];
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d%d",&u,&v);
            if(~v){
                adde(u,v);
                adde(v,u);
            }
            else{
                rt=u;
            }
        }
        dfs(rt);
        scanf("%d",&m);
        for(int i=1;i<=m;i++){
            scanf("%d%d",&u,&v);
            tmp=lca(u,v);
            if(tmp==u){
                puts("1");
            }else if(tmp==v){
                puts("2");
            }else{
                puts("0");
            }
        }
        return 0;
    }

    这么多水题忽然好颓废啊!
    T9 luogu1967&&xsy2018 倍增+最大生成树
    这里写图片描述

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int n,m,q,u,v,cnt,pa[10005],head[10005],to[20005],nxt[20005],dd[20005],fa[10005][20],minn[10005][20];
    int dep[10005];
    struct edge{
        int u,v,d;
    }e[50005];
    bool cmp(edge a,edge b){
        return a.d>b.d;
    }
    int find(int u){
        return u==pa[u]?u:pa[u]=find(pa[u]);
    }
    void adde(int u,int v,int d){
        to[++cnt]=v;
        nxt[cnt]=head[u];
        dd[cnt]=d;
        head[u]=cnt;
    }
    void dfs(int u){
        for(int i=1;(1<<i)<=dep[u];i++){
            fa[u][i]=fa[fa[u][i-1]][i-1];
            minn[u][i]=min(minn[u][i-1],minn[fa[u][i-1]][i-1]);
        }
        int v;
        for(int i=head[u];i;i=nxt[i]){
            v=to[i];
            if(v!=fa[u][0]){
                fa[v][0]=u;
                minn[v][0]=dd[i];
                dep[v]=dep[u]+1;
                dfs(v);
            }
        }
    }
    int solve(int u,int v){
        if(dep[u]<dep[v]){
            swap(u,v);
        }
        int ans=0x7fffffff,d=dep[u]-dep[v];
        for(int i=0;(1<<i)<=d;i++){
            if(d&(1<<i)){
                ans=min(ans,minn[u][i]);
                u=fa[u][i];
            }
        }
        if(u==v){
            return ans;
        }
        for(int i=16;i>=0;i--){
            if(fa[u][i]!=fa[v][i]){
                ans=min(ans,min(minn[u][i],minn[v][i]));
                u=fa[u][i];
                v=fa[v][i];
            }
        }
        if(fa[u][0]){
            return min(ans,min(minn[u][0],minn[v][0]));
        }else{
            return -1;
        }
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            pa[i]=i;
        }
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].d);
        }
        sort(e+1,e+m+1,cmp);
        for(int i=1;i<=m;i++){
            u=find(e[i].u),v=find(e[i].v);
            if(u!=v){
                adde(e[i].u,e[i].v,e[i].d);
                adde(e[i].v,e[i].u,e[i].d);
                pa[v]=u;
            }
        }
        dfs(1);
        scanf("%d",&q);
        for(int i=1;i<=q;i++){
            scanf("%d%d",&u,&v);
            printf("%d
    ",solve(u,v));
        }
        return 0;
    }

    T10 CF587C&&xsy2414 倍增+归并
    这里写图片描述

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int n,m,q,u,v,t,tmp,cnt,ans[15],a[100005],head[100005],to[200005],nxt[200005],fa[100005][20],dep[100005],minn[100005][20][15];
    void adde(int u,int v){
        to[++cnt]=v;
        nxt[cnt]=head[u];
        head[u]=cnt;
    }
    void merge(int a[],int b[],int d[]){
        int i=1,j=1,k=0,c[15];
        while(i<=a[0]&&j<=b[0]&&k<10){
            if(a[i]<b[j]){
                c[++k]=a[i++];
            }else{
                c[++k]=b[j++];
            }
        }
        while(i<=a[0]&&k<10){
            c[++k]=a[i++];
        }
        while(j<=b[0]&&k<10){
            c[++k]=b[j++];
        }
        for(int i=1;i<=k;i++){
            d[i]=c[i];
        }
        d[0]=k;
    }
    void dfs(int u){
        memcpy(minn[u][1],minn[fa[u][1]][0],sizeof(minn[fa[u][1]][0]));
        for(int i=2;i<=17;i++){
            fa[u][i]=fa[fa[u][i-1]][i-1];
            merge(minn[u][i-1],minn[fa[u][i-1]][i-1],minn[u][i]);
        }
        int v;
        for(int i=head[u];i;i=nxt[i]){
            v=to[i];
            if(v!=fa[u][1]){
                fa[v][1]=u;
                dep[v]=dep[u]+1;
                dfs(v);
            }
        }
    } 
    void solve(int u,int v,int t){
        if(dep[u]<dep[v]){
            swap(u,v);
        }
        int d=dep[u]-dep[v];
        memcpy(ans,minn[u][0],sizeof(minn[u][0]));
        for(int i=1;i<=17;i++){
            if(d&(1<<(i-1))){
                merge(ans,minn[u][i],ans);
                u=fa[u][i];
            }
        }
        if(u!=v){
            merge(ans,minn[v][0],ans);
            for(int i=17;i>=1;i--){
                if(fa[u][i]!=fa[v][i]){
                    merge(ans,minn[u][i],ans);
                    merge(ans,minn[v][i],ans);
                    u=fa[u][i];
                    v=fa[v][i];
                }
            }
            merge(ans,minn[u][1],ans);
        }
        ans[0]=min(ans[0],t);
        printf("%d ",ans[0]);
        for(int i=1;i<=ans[0];i++){
            printf("%d ",ans[i]);
        }
        puts("");
    }
    int main(){
        scanf("%d%d%d",&n,&m,&q);
        for(int i=1;i<n;i++){
            scanf("%d%d",&u,&v);
            adde(u,v);
            adde(v,u);
        }
        for(int i=1;i<=m;i++){
            scanf("%d",&tmp);
            minn[tmp][0][++minn[tmp][0][0]]=i;
        }
        dfs(1);
        for(int i=1;i<=q;i++){
            scanf("%d%d%d",&u,&v,&t);
            solve(u,v,t);
        }
        return 0;
    }

    T11 bzoj3545&&bzoj3551 并查集+谜之建树+倍增+线段树
    这里写图片描述
    这里写图片描述

    #include<cstdio>
    #include<algorithm>
    #include<vector>
    using namespace std;
    inline int rd()
    {
        int x=0,f=1;char ch=getchar();
        while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    const int N=100005;
    int n,m,q,tot,cnt,idx,h[N],pa[2*N],val[2*N],head[N*2],to[N*2],nxt[N*2],dep[N*2],fa[N*2][20],mx[N*2][20];
    int lc[50*N],rc[50*N],sumv[50*N],pos[N*3],root[N*3],bg[N*2],ed[N*2];
    bool vis[N*2];
    vector<int> V;
    struct edge
    {
        int u,v,d;
    }a[5*N];
    bool cmp(edge a,edge b)
    {
        return a.d<b.d;
    }
    int findrt(int u)
    {
        return u==pa[u]?u:pa[u]=findrt(pa[u]);
    }
    void adde(int u,int v)
    {
        to[++cnt]=v;
        nxt[cnt]=head[u];
        head[u]=cnt;
    }
    void dfs(int u)
    {
        vis[u]=true;
        pos[++pos[0]]=u;
        for(int i=1;(1<<i)<=dep[u];i++)
        {
            fa[u][i]=fa[fa[u][i-1]][i-1];
            mx[u][i]=max(mx[u][i-1],mx[fa[u][i-1]][i-1]);
        }
        for(int i=head[u];i;i=nxt[i])
        {
            dep[to[i]]=dep[u]+1;
            fa[to[i]][0]=u;
            mx[to[i]][0]=val[u];
            dfs(to[i]);
        }
        if(u>n) pos[++pos[0]]=u;
    }
    void update(int &x,int y,int l,int r,int k)
    {
        x=++idx;
        sumv[x]=sumv[y]+1;
        lc[x]=lc[y];
        rc[x]=rc[y];
        if(l==r) return;
        int mid=(l+r)/2;
        if(k<=mid) update(lc[x],lc[y],l,mid,k);
        else update(rc[x],rc[y],mid+1,r,k);
    }
    int query(int x,int y,int l,int r,int k)
    {
        if(l==r) return l;
        int mid=(l+r)/2,sum=sumv[lc[y]]-sumv[lc[x]];
        if(k<=sum) return query(lc[x],lc[y],l,mid,k);
        else return query(rc[x],rc[y],mid+1,r,k-sum);
    }
    void build()
    {
        tot=n;
        sort(a+1,a+m+1,cmp);
        for(int i=1;i<=m;i++)
        {
            int p=findrt(a[i].u),q=findrt(a[i].v);
            if(p^q)
            {
                tot++;
                pa[p]=pa[q]=tot;
                val[tot]=a[i].d;
                adde(tot,p);
                adde(tot,q);
                if(tot==n*2-1) break;
            }
        }
        for(int i=1;i<=n;i++)
            if(!vis[i]) dfs(findrt(i));
        for(int i=1;i<=pos[0];i++)
        {
            int tmp=pos[i];
            if(tmp<=n) update(root[i],root[i-1],1,n,h[tmp]);
            else
            {
                root[i]=root[i-1];
                if(!bg[tmp]) bg[tmp]=i;
                else ed[tmp]=i;
            }
        }
    }
    int find(int x,int v)
    {
        for(int i=17;i>=0;i--)
            if(dep[x]>=(1<<i)&&mx[x][i]<=v)
                x=fa[x][i];
        return x;
    }
    void solve()
    {
        int ans=0,v,x,k;
        for(int i=1;i<=q;i++)
        {
            v=rd(),x=rd(),k=rd();
            if(ans!=-1) v^=ans,x^=ans,k^=ans;
            int t=find(v,x);
            int a=root[bg[t]],b=root[ed[t]];
            if(sumv[b]-sumv[a]<k) ans=-1;
            else ans=V[query(a,b,1,n,sumv[b]-sumv[a]-k+1)-1];
            printf("%d
    ",ans);
        }
    }
    int main()
    {
        n=rd(),m=rd(),q=rd();
        for(int i=1;i<=n;i++)
            V.push_back(h[i]=rd());
        sort(V.begin(),V.end());
        for(int i=1;i<=n;i++)
            h[i]=lower_bound(V.begin(),V.end(),h[i])-V.begin()+1;
        for(int i=1;i<=2*n;i++) pa[i]=i;
        for(int i=1;i<=m;i++)
            a[i].u=rd(),a[i].v=rd(),a[i].d=rd();
        build();
        solve();
        return 0;
    }

    终于写完了,好嗨森!

  • 相关阅读:
    C# 文本,图片 与 Base64的相互转换
    vue3.x 中的自定义组件及使用
    vue 的TodoList 小Demo
    vue中的条件渲染 v-show、v-if、v-else、v-else-if
    vue 使用$refs获取表单内容及v-model双向数据绑定
    python-异常处理&操作数据库&网络编程
    python-接口开发
    python-数据库&邮件
    python-函数和模块
    python-函数&list&dic&集合&文件读取
  • 原文地址:https://www.cnblogs.com/2016gdgzoi471/p/9476914.html
Copyright © 2011-2022 走看看