P5064 [Ynoi2014] 等这场战争结束之后

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('\n');
	return 0;
}
posted @ 2021-04-16 16:00  __Anchor  阅读(41)  评论(0编辑  收藏  举报