COJ983 WZJ的数据结构(负十七)

显然是动态树裸题:O(mlogn)

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
using namespace std;
inline int read()
{
    int x=0,f=1;char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    return x*f;
}
const int maxn=100010;
int sumv[maxn],val[maxn],pre[maxn],fa[maxn],ch[maxn][2],flip[maxn];
void maintain(int x) {sumv[x]=sumv[ch[x][0]]+sumv[ch[x][1]]+val[x];}
void pushdown(int x)
{
    if(!flip[x]) return;
    flip[ch[x][0]]^=1;flip[ch[x][1]]^=1;
    swap(ch[x][0],ch[x][1]);flip[x]=0;
}
void rotate(int x,int d)
{
    pushdown(x);int y=pre[x],z=pre[y];
    pre[ch[x][d]]=y;ch[y][d^1]=ch[x][d];
    pre[x]=z;ch[z][ch[z][1]==y]=x;
    pre[y]=x;ch[x][d]=y;maintain(y);
}
void splay(int x)
{
    int rt=x;while(pre[rt]) rt=pre[rt];
    if(rt!=x)
    {
        fa[x]=fa[rt];fa[rt]=0;
        while(pre[x]) pushdown(pre[x]),rotate(x,ch[pre[x]][0]==x);
        maintain(x);
    }
    else pushdown(x);
}
void access(int x)
{
    for(int y=0;x;x=fa[x])
    {
        splay(x);pre[ch[x][1]]=0;fa[ch[x][1]]=x;
        ch[x][1]=y;pre[y]=x;fa[y]=0;
        maintain(x);y=x;
    }
}
int findrt(int x)
{
    access(x);splay(x);
    while(ch[x][0]) x=ch[x][0];return x;
}
void makeroot(int x) {access(x);splay(x);flip[x]^=1;}
void link(int x,int y) {makeroot(x);fa[x]=y;}
void query(int x,int y) {makeroot(x);access(y);splay(y);printf("%d
",sumv[y]);}
int main()
{
    int n=read();
    for(int i=1;i<=n;i++) val[i]=read();
    int m=read();
    while(m--)
    {
        char cmd=getchar();while(!isalpha(cmd)) cmd=getchar();
        int x=read(),y=read();
        if(cmd=='e')
        {
            if(findrt(x)==findrt(y)) query(x,y);
            else puts("impossible");
        }
        else
        {
            if(findrt(x)==findrt(y)) puts("no");
            else link(x,y),puts("yes");
        }
    }
    return 0;
}
View Code

可以写个启发式合并O(mlog^2n)

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
using namespace std;
inline int read()
{
    int x=0,f=1;char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    return x*f;
}
const int maxn=100010;
int first[maxn],next[maxn*2],to[maxn*2],e;
void AddEdge(int u,int v)
{
    to[++e]=v;next[e]=first[u];first[u]=e;
    to[++e]=u;next[e]=first[v];first[v]=e;
}
int val[maxn],pa[maxn],s[maxn];
inline int findset(int x) {return pa[x]==x?x:pa[x]=findset(pa[x]);}
int fa[maxn][12],sum[maxn],dep[maxn];
void dfs(int x)
{
    sum[x]=sum[fa[x][0]]+val[x];dep[x]=dep[fa[x][0]]+1;
    for(int i=1;i<12;i++) fa[x][i]=fa[fa[x][i-1]][i-1];
    for(int i=first[x];i;i=next[i]) if(to[i]!=fa[x][0]) fa[to[i]][0]=x,dfs(to[i]);
}
void query(int x,int y)
{
    int ret=sum[x]+sum[y],lca;
    if(dep[x]<dep[y]) swap(x,y);
    for(int i=11;i>=0;i--) if((1<<i)<=dep[x]-dep[y]) x=fa[x][i];
    for(int i=11;i>=0;i--) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
    lca=(x==y)?x:fa[x][0];
    printf("%d
",ret-sum[lca]-sum[fa[lca][0]]);
}
int main()
{
    int n=read();
    for(int i=1;i<=n;i++) sum[i]=val[i]=read(),pa[i]=i,s[i]=1;
    int m=read();
    while(m--)
    {
        char cmd=getchar();while(!isalpha(cmd)) cmd=getchar();
        int x=read(),y=read();
        if(cmd=='e')
        {
            int p1=findset(x),p2=findset(y);
            if(x==y) printf("%d
",val[x]);
            else if(p1==p2) query(x,y);
            else puts("impossible");
        }
        else if(cmd=='b')
        {
            int p1=findset(x),p2=findset(y);
            if(p1==p2) {puts("no");continue;}puts("yes");
            if(s[p1]>s[p2]) swap(p1,p2),swap(x,y);
            pa[p1]=p2;s[p2]+=s[p1];fa[x][0]=y;AddEdge(x,y);
            dfs(x);
        }
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/4543682.html