【BZOJ2733】永无乡(线段树,并查集)

【BZOJ2733】永无乡(线段树,并查集)

题面

BZOJ

题解

线段树合并

线段树合并是一个很有趣的姿势

前置技能:动态开点线段树

具体实现:每次合并两棵线段树的时候,假设叫做\(t1,t2\),其中要把\(t2\)合并进\(t1\)

假设当前位置\(t1\)没有节点,则直接把\(t2\)的这个位置给\(t1\)(直接接上去就好啦)

如果\(t2\)这个位置没有节点,那么直接\(return\)

否则,两个位置都有节点,把两个节点的信息合并,然后递归合并左右子树

简单的代码如下:

void MergeNode(int &r1,int r2)
{
	if(!r1){r1=r2;return;}
	if(!r2)return;
	t[r1].v+=t[r2].v;
	MergeNode(t[r1].ls,t[r2].ls);
	MergeNode(t[r1].rs,t[r2].rs);
}

回到这道题目

对于每一个联通快维护一个值域线段树

每次在线段树上二分一下第\(K\)大就好了

每次修桥相当于合并两棵线段树

用并查集维护一下联通快就可以啦,多简单

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 120000
inline int read()
{
    RG int x=0,t=1;RG char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=-1,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return x*t;
}
int n,m,Q;
struct Node
{
	int ls,rs;
	int v;
}t[MAX<<4];
int tot;
int a[MAX];
void Modify(int &x,int l,int r,int p)
{
	if(!x)x=++tot;t[x].v++;
	if(l==r)return;
	int mid=(l+r)>>1;
	if(p<=mid)Modify(t[x].ls,l,mid,p);
	else Modify(t[x].rs,mid+1,r,p);
}
void MergeNode(int &r1,int r2)
{
	if(!r1){r1=r2;return;}
	if(!r2)return;
	t[r1].v+=t[r2].v;
	MergeNode(t[r1].ls,t[r2].ls);
	MergeNode(t[r1].rs,t[r2].rs);
}
int Query(int x,int l,int r,int K)
{
	if(l==r)return l;
	int mid=(l+r)>>1;
	if(K<=t[t[x].ls].v)return Query(t[x].ls,l,mid,K);
	else return Query(t[x].rs,mid+1,r,K-t[t[x].ls].v);
}
int f[MAX],rt[MAX];
int getf(int x){return x==f[x]?x:f[x]=getf(f[x]);}
int main()
{
	n=read();m=read();
	for(int i=1;i<=n;++i)
	{
		int x=read();a[x]=i;
		Modify(rt[f[i]=i],1,n,x);
	}
	while(m--)
	{
		int a=read(),b=read();
		a=getf(a);b=getf(b);
		if(a==b)continue;
		f[b]=a;
		MergeNode(rt[a],rt[b]);
	}
	Q=read();
	char opt[5];
	while(Q--)
	{
		scanf("%s",opt);
		if(opt[0]=='Q')
		{
			int x=read(),k=read();
			x=getf(x);
			if(t[rt[x]].v<k)puts("-1");
			else printf("%d\n",a[Query(rt[x],1,n,k)]);
		}
		else
		{
			int u=read(),v=read();
			u=getf(u),v=getf(v);
			if(u==v)continue;
			f[v]=u;
			MergeNode(rt[u],rt[v]);
		}
	}
	return 0;
}

posted @ 2018-03-13 17:10  小蒟蒻yyb  阅读(252)  评论(0编辑  收藏  举报