主席树+启发式合并(LT) BZOJ3123

好久没做题了,写道SBT又RE又T

查询:主席树裸题。

修改:对于两个树合并重建小的树。

注意fa[x][i]重新计算时要清空

#include<cstdio> 
#include<cctype> 
#include<cstring> 
#include<algorithm> 
using namespace std; 
inline int read() 
{ 
    char c=getchar();int x=0,sig=1; 
    for(;!isdigit(c);c=getchar()) if(c=='-') sig=-1; 
    for(;isdigit(c);c=getchar()) x=x*10+c-'0'; 
    return x*sig; 
} 
inline void print(int x) 
{ 
    int buf[10],l=0; 
    if(!x) l++; 
    while(x) buf[++l]=x%10,x/=10; 
    for(;l;l--) putchar(buf[l]+'0'); 
    putchar('
'); 
} 
const int maxn=80010; 
const int maxnode=10000010; 
int ls[maxnode],rs[maxnode],s[maxnode],ToT; 
void update(int& y,int x,int l,int r,int pos) 
{ 
     s[y=++ToT]=s[x]+1;if(l==r) return; 
     int mid=l+r>>1;ls[y]=ls[x];rs[y]=rs[x]; 
     if(pos<=mid) update(ls[y],ls[x],l,mid,pos); 
     else update(rs[y],rs[x],mid+1,r,pos); 
} 
int query(int x1,int x2,int y1,int y2,int l,int r,int k) 
{ 
    if(l==r) return l; 
    int mid=l+r>>1,k2=s[ls[y1]]+s[ls[y2]]-s[ls[x1]]-s[ls[x2]]; 
    if(k<=k2) return query(ls[x1],ls[x2],ls[y1],ls[y2],l,mid,k); 
    return query(rs[x1],rs[x2],rs[y1],rs[y2],mid+1,r,k-k2); 
} 
int n,m,q,val[maxn],tmp[maxn],root[maxn],lastans; 
int first[maxn],next[maxn*2],to[maxn*2],e,fa[maxn][20],dep[maxn]; 
int pa[maxn],sz[maxn];
void AddEdge(int a,int b) 
{ 
    to[++e]=b;next[e]=first[a];first[a]=e; 
    to[++e]=a;next[e]=first[b];first[b]=e; 
} 
void dfs(int x,int f) 
{ 
    dep[x]=dep[fa[x][0]=f]+1;update(root[x],root[f],1,n,val[x]);
    sz[pa[x]]++;
    for(int i=1;i<17;i++) fa[x][i]=fa[fa[x][i-1]][i-1]; 
    for(int i=first[x];i;i=next[i]) if(to[i]!=f) pa[to[i]]=pa[x],dfs(to[i],x); 
} 
int lca(int p,int q) 
{ 
    if(dep[p]<dep[q]) swap(p,q);
    for(int i=19;i>=0;i--) if((1<<i)<=dep[p]-dep[q]) p=fa[p][i];
    for(int i=19;i>=0;i--) if(fa[p][i]!=fa[q][i]) p=fa[p][i],q=fa[q][i];
    return p==q?p:fa[p][0];
}
int main() 
{ 
    read();n=read();m=read();q=read(); 
    for(int i=1;i<=n;i++) tmp[i]=val[i]=read();
    sort(tmp+1,tmp+n+1); 
    for(int i=1;i<=n;i++) val[i]=lower_bound(tmp+1,tmp+n+1,val[i])-tmp; 
    for(int i=0;i<m;i++) AddEdge(read(),read());
    for(int i=1;i<=n;i++) if(!fa[i][0]) pa[i]=i,dfs(i,0); 
    for(int i=0;i<q;i++) 
    { 
        char tp=getchar(); 
        while(!isalpha(tp)) tp=getchar(); 
        if(tp=='Q') 
        { 
            int x=read()^lastans,y=read()^lastans,k=read()^lastans; 
            int c=lca(x,y); 
            print(lastans=tmp[query(root[c],root[fa[c][0]],root[x],root[y],1,n,k)]); 
        }
        else
        { 
            int u=read()^lastans,v=read()^lastans; 
            int x=pa[u],y=pa[v]; 
            if(sz[x]>sz[y]) swap(x,y),swap(u,v); 
            pa[u]=y;AddEdge(u,v);dfs(u,v); 
        } 
    } 
    return 0; 
}
View Code
原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/4506292.html