[SDOI2013]森林 主席樹 啟發式合併
阿新 • • 發佈:2018-12-16
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;
}