P5064 [Ynoi2014] 等这场战争结束之后(值域分块+并查集)
建出操作树,离散化,然后并查集+值域分块维护。
代码:
#include<bits/stdc++.h>
#define PII pair<int,int>
using namespace std;
template <typename T>
inline void read(T &x){
x=0;bool f=false;char ch=getchar();
while(!isdigit(ch)){if(ch=='-'){f=true;}ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
x=f?-x:x;
return ;
}
template <typename T>
inline void write(T x){
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10^48);
return ;
}
const int N=1e5+5,M=36;
int n,m,a[N],fa[N],siz[N],B,t=2778,id[N],RES[N],head[N],idx,top;
short int s[N][M+2];
struct edge{int v,nex;}e[N];
struct opt{int op,x,y;}p[N];
int Getfa(int x){if(x==fa[x])return x;return Getfa(fa[x]);}
PII stk[N];
void Merge(int x,int y){
x=Getfa(x),y=Getfa(y);
if(x==y) return ;
if(siz[x]<siz[y]) swap(x,y);
fa[y]=x,siz[x]+=siz[y];
for(int now=0;now<=B;now++) s[x][now]+=s[y][now];
stk[++top]=make_pair(x,y);
return ;
}
void Delete(int p){
while(p--){
PII x=stk[top--];siz[x.first]-=siz[x.second],fa[x.second]=x.second;
for(int now=0;now<=B;now++) s[x.first][now]-=s[x.second][now];
}
return ;
}
int Query(int x,int y){
x=Getfa(x);
if(y>siz[x]) return -1;
int pos=0;
while(s[x][pos]<y){
y-=s[x][pos];
pos++;
}
for(int now=0;now<t;now++){
if(Getfa(id[pos*t+now])==x) y--;
if(y==0) return a[id[pos*t+now]];
}
}
void Add(int u,int v){e[++idx].v=v;e[idx].nex=head[u];head[u]=idx;}
bool cmp(int x,int y){return a[x]<a[y];}
void Dfs(int x){
int Top=top;
if(p[x].op==1) Merge(p[x].x,p[x].y);
else if(p[x].op==3){RES[x]=Query(p[x].x,p[x].y);}
for(int now=head[x];now;now=e[now].nex){int y=e[now].v;Dfs(y);}
if(p[x].op==1){int len=top-Top;Delete(len);}
}
int main(){
read(n),read(m);
B=(n/t)+1;
for(int now=1;now<=n;now++) read(a[now]),id[now]=now;
sort(id+1,id+n+1,cmp);
for(int now=1;now<=n;now++) fa[now]=now,s[id[now]][(now/t)]=siz[now]=1;
for(int now=1;now<=m;now++){
read(p[now].op),read(p[now].x);
if(p[now].op==2) Add(p[now].x,now);
else read(p[now].y),Add(now-1,now);
}
Dfs(0);
for(int now=1;now<=m;now++) if(p[now].op==3) write(RES[now]),putchar('
');
return 0;
}