洛谷 P3302 [SDOI2013]森林
题解:
#include<queue> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define MAXN 160001 #define D 15 using namespace std; char ch[5]; int t,x,y,z; int n,m,qq,tot,cut,ans,father[MAXN],dis[MAXN]; int head[MAXN],size[MAXN],deep[MAXN],root[MAXN],s[MAXN],fa[MAXN][D+5]; struct edge { int v,next; } e[MAXN*2]; struct data { int lc,rc,size; } tree[MAXN*75]; struct node { int x,o; } a[MAXN]; void add(int u,int v) { e[++cut].v=v; e[cut].next=head[u]; head[u]=cut; } bool cmp(const node &x,const node &y) { if(x.x==y.x) return x.o<y.o; return x.x<y.x; } int find(int x) { return x!=father[x]?father[x]=find(father[x]):x; } void change(int &k,int last,int l,int r,int x) { k=++tot; tree[k].lc=tree[last].lc,tree[k].rc=tree[last].rc; tree[k].size=tree[last].size+1; if(l==r) return ; int mid=(l+r)>>1; if(x<=mid) change(tree[k].lc,tree[last].lc,l,mid,x); else change(tree[k].rc,tree[last].rc,mid+1,r,x); return ; } int query(int L,int R,int lc,int falc,int l,int r,int k) { if(l==r) return l; int sum=tree[tree[R].lc].size+tree[tree[L].lc].size- tree[tree[lc].lc].size-tree[tree[falc].lc].size; int mid=l+r>>1; if(sum>=k) return query(tree[L].lc,tree[R].lc,tree[lc].lc,tree[falc].lc,l,mid,k); else return query(tree[L].rc,tree[R].rc,tree[lc].rc,tree[falc].rc,mid+1,r,k-sum); } void dfs1(int u,int f) { size[u]=1; fa[u][0]=f; int p=lower_bound(s+1,s+n+1,a[u].x)-s; change(root[u],root[f],1,n,p); for(int i=head[u]; i; i=e[i].next) { int v=e[i].v; if(v!=f) deep[v]=deep[u]+1,dfs1(v,u),size[u]+=size[v]; } return ; } void get_father() { for(int j=1; j<=D; j++) for(int i=1; i<=n; i++) fa[i][j]=fa[fa[i][j-1]][j-1]; return ; } int get_same(int u,int x) { for(int i=0; i<=D; i++) if(x&(1<<i)) u=fa[u][i]; return u; } int lca(int x,int y) { if(deep[x]<deep[y]) swap(x,y); x=get_same(x,deep[x]-deep[y]); if(x==y) return x; for(int i=D; i>=0; i--) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; return fa[x][0]; } void slovequery(int x,int y,int k) { int lc=lca(x,y); ans=query(root[x],root[y],root[lc],root[fa[lc][0]],1,n,k); ans=s[ans]; printf("%d\n",ans); return ; } void slove(int u,int f) { fa[u][0]=f; deep[u]=deep[f]+1; int p=lower_bound(s+1,s+n+1,a[u].x)-s; change(root[u],root[f],1,n,p); for(int i=1; i<=D; i++) fa[u][i]=fa[fa[u][i-1]][i-1]; for(int i=head[u]; i; i=e[i].next) { int v=e[i].v; if(v!=f) slove(v,u); } return ; } void union_(int x,int y) { int l1=find(x),l2=find(y); if(size[l1]>size[l2]) swap(l1,l2),swap(x,y); add(x,y),add(y,x); father[l1]=l2,size[l1]+=size[l2]; slove(x,y); return ; } int main() { cin>>t>>n; cin>>m>>qq; for(int i=1; i<=n; i++) father[i]=i,cin>>a[i].x,a[i].o=i,s[i]=a[i].x; sort(s+1,s+n+1); for(int i=1; i<=m; i++) { cin>>x>>y,add(x,y),add(y,x); int l1=find(x),l2=find(y); father[l2]=l1; } for(int i=1; i<=n; i++) if(!fa[i][0]) dfs1(i,0); get_father(); while(qq--) { scanf("%s",ch); if(ch[0]=='Q') { cin>>x>>y>>z; x^=ans,y^=ans,z^=ans; slovequery(x,y,z); } else { cin>>x>>y; x^=ans,y^=ans; union_(x,y); } } return 0; }
一世安宁