[SDOI2013]森林 主席树 启发式合并
Code:
#include<cstdio> #include<algorithm> #include<iostream> #include<string> #include<cstring> #define REP(i,a,n) for(int i=a;i<=n;++i) #define CLR(x,c) memset(x,c,sizeof x) int read(){ int a; scanf("%d",&a); return a;} using namespace std; void SetIO(string a){ string in = a + ".in"; freopen(in.c_str(), "r" ,stdin); } const int maxn=80000+5; int n, m, T; int val[maxn], Sorted[maxn]; void Discrete(){ sort(Sorted + 1, Sorted + 1 + n); for(int i = 1;i <= n; ++i){ val[i] = lower_bound(Sorted + 1, Sorted + 1 + n, val[i]) - Sorted; } } int head[maxn], nex[maxn<<1], to[maxn<<1], edges; void add_edge(int u, int v){ nex[++edges] = head[u]; head[u] = edges; to[edges] = v; } void Read(){ n=read(),n=read(),m=read(), T=read(); REP(i,1,n) val[i]=read(), Sorted[i] = val[i]; REP(i,1,m){ int a=read(),b=read(); add_edge(a,b); add_edge(b,a); } } const int const_Tree=300; int root[maxn],numv[maxn*const_Tree]; struct Chair_Tree{ int cnt_Tree, lson[maxn*const_Tree], rson[maxn * const_Tree]; void build(int l,int r,int &o){ if(l > r)return; o = ++cnt_Tree; int mid=(l + r) >> 1; build(l, mid, lson[o]); build(mid + 1, r, rson[o]); } int insert(int l, int r, int o, int pos){ int oo=++cnt_Tree; lson[oo] = lson[o]; rson[oo] = rson[o]; numv[oo] = numv[o] + 1; if(l == r) return oo; int mid=(l+r)>>1; if(pos <= mid) lson[oo] = insert(l,mid,lson[o],pos); else rson[oo] = insert(mid+1,r,rson[o],pos); return oo; } int query(int l,int r,int u,int v,int lca,int flca,int k){ if(l==r)return l; int lsum=numv[lson[u]]+numv[lson[v]]-numv[lson[lca]]-numv[lson[flca]]; int mid=(l+r)>>1; if(k<=lsum) return query(l,mid,lson[u],lson[v],lson[lca],lson[flca],k); else return query(mid+1,r,rson[u],rson[v],rson[lca],rson[flca],k-lsum); } }Tree; const int log_Tree = 17; int dep[maxn], f[log_Tree + 3][maxn],siz[maxn]; int dfs(int u,int fa,int depth){ f[0][u]=fa; siz[u]=1; dep[u]=depth; REP(i,1,log_Tree) f[i][u] = f[i-1][f[i-1][u]]; root[u]=Tree.insert(1,n,root[fa],val[u]); for(int v = head[u];v;v = nex[v]){ if(to[v]==fa) continue; siz[u]+=dfs(to[v],u,depth+1); } return siz[u]; } void Build(){ REP(i,1,n) if(!dep[i]) dfs(i, 0, 1); } int get_lca(int a,int b){ if(dep[a] > dep[b]) swap(a,b); if(dep[a] != dep[b]){ for(int i=log_Tree;i>=0;--i){ if(dep[f[i][b]]>=dep[a]) b=f[i][b]; } } if(a==b)return a; for(int i=log_Tree;i>=0;--i){ if(f[i][a]!=f[i][b]){ a=f[i][a]; b=f[i][b]; } } return f[0][a]; } void Work(){ int lastans=0; REP(i,1,T) { char opt[3]; scanf("%s",opt); int u,v,k; u=read(),v=read(); u^=lastans, v ^= lastans; if(opt[0] == 'Q'){ k=read(); k^=lastans; int lca=get_lca(u,v); int flca=f[0][lca]; lastans=Tree.query(1,n,root[u],root[v],root[lca],root[flca],k); lastans=Sorted[lastans]; printf("%d\n",lastans); } if(opt[0] == 'L'){ add_edge(u,v); add_edge(v,u); if(siz[u]>siz[v]){ siz[u]+=dfs(v,u,dep[u]+1); } else{ siz[v]+=dfs(u,v,dep[v]+1); } } } } void Init(){ Read(); Discrete(); Build(); } int main(){ SetIO("input"); Init(); Work(); return 0; }