【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\n",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\n",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\n",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('\n');
    }
    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\n",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\n",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\n",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\n",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\n",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;
}

终于写完了,好嗨森!

posted @ 2017-12-02 08:19  一剑霜寒十四洲  阅读(160)  评论(0编辑  收藏  举报