zoukankan      html  css  js  c++  java
  • [HNOI2012]永无乡

    [HNOI2012]永无乡https://www.luogu.org/problemnew/show/P3224

    题目描述:

    永无乡包含 (n) 座岛,编号从 (1)(n) ,每座岛都有自己的独一无二的重要度,按照重要度可以将这 (n) 座岛排名,名次用 (1)(n) 来表示。某些岛之间由巨大的桥连接,通过桥可以从一个岛到达另一个岛。如果从岛 (a) 出发经过若干座(含 (0) 座)桥可以到达岛 (b) ,则称岛 (a) 和岛 (b) 是连通的。
    现在有两种操作:
    (B) (x) (y) 表示在岛 (x) 与岛 (y) 之间修建一座新桥。
    (Q) (x) (k) 表示询问当前与岛 (x) 连通的所有岛中第 (k) 重要的是哪座岛,即所有与岛 (x) 连通的岛中重要度排名第 (k) 小的岛是哪座,请你输出那个岛的编号。

    输入格式:

    第一行是用空格隔开的两个正整数 (n)(m) ,分别表示岛的个数以及一开始存在的桥数。
    接下来的一行是用空格隔开的 (n) 个数,依次描述从岛 (1) 到岛 (n) 的重要度排名。随后的 (m) 行,每行是用空格隔开的两个正整数 (a_i)(b_i) ,表示一开始就存在一座连接岛 (a_i) 和岛 (b_i) 的桥。
    后面剩下的部分描述操作,该部分的第一行是一个正整数 (q) ,表示一共有 (q) 个操作,接下来的 (q) 行依次描述每个操作,操作的 格式如上所述,以大写字母 (Q)(B) 开始,后面跟两个不超过 (n) 的正整数,字母与数字以及两个数字之间用空格隔开。

    输出格式:

    对于每个 (Q) (x) (k) 操作都要依次输出一行,其中包含一个整数,表示所询问岛屿的编号。如果该岛屿不存在,则输出 (−1)

    输入样例:

    5 1
    4 3 2 5 1
    1 2
    7
    Q 3 2
    Q 2 1
    B 2 3
    B 1 5
    Q 2 1
    Q 2 4
    Q 2 3

    输出样例:

    -1
    2
    5
    1
    2

    说明

    对于 20% 的数据 (n≤1000,q≤1000)
    对于 100% 的数据 (n≤100000,m≤n,q≤300000)


    并查集维护连通性,对每个联通块开值域线段树
    (id[])维护线段树上的点对应的编号
    对于查询操作:在当前的所在线段树中直接查询
    对于合并操作:用(Merge())函数直接合并两棵线段树
    复杂度:(O(qlogn))
    注意动态开点

    #define RG register
    #include<cstdio>
    using namespace std;
    const int N=1e5+5;
    inline int read()
    {
    	RG int x=0,w=1;RG char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    	return x*w;
    }
    int n,m,Q,cnt;
    int val[N],fa[N],root[N],id[N];
    int ls[N<<5],rs[N<<5],sum[N<<5];
    int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
    void insert(int &root,int l,int r,int val)
    {
    	if(!root)root=++cnt;
    	if(l==r){sum[root]=1;return;}
    	int mid=(l+r)>>1;
    	if(val<=mid)insert(ls[root],l,mid,val);
    	else insert(rs[root],mid+1,r,val);
    	sum[root]=sum[ls[root]]+sum[rs[root]];
    }
    int Query(int root,int l,int r,int k)
    {
    	if(l==r)return l;
    	int mid=(l+r)>>1;
    	if(sum[ls[root]]>=k)return Query(ls[root],l,mid,k);
    	else return Query(rs[root],mid+1,r,k-sum[ls[root]]);
    }
    int Merge(int a,int b)
    {
    	if(!a||!b)return a+b;
    	ls[a]=Merge(ls[a],ls[b]);
    	rs[a]=Merge(rs[a],rs[b]);
    	sum[a]=sum[ls[a]]+sum[rs[a]];
    	return a;
    }
    int main()
    {
    	n=read();
    	m=read();
    	for(int i=1;i<=n;i++)val[i]=read(),fa[i]=i;
    	for(int i=1;i<=m;i++)
    	{
    		RG int x=find(read()),y=find(read());
    		fa[x]=y;
    	}
    	for(int i=1;i<=n;i++)
    	{
    		insert(root[find(i)],1,n,val[i]);
    		id[val[i]]=i;
    	}
    	Q=read();
    	RG int a,b;
    	RG char act[2];
    	while(Q--)
    	{
    		scanf("%s",act);
    		a=read();b=read();
    		if(act[0]=='Q')
    		{
    			a=find(a);
    			if(sum[root[a]]<b)puts("-1");
    			else printf("%d
    ",id[Query(root[a],1,n,b)]);
    		}
    		else
    		{
    			a=find(a);b=find(b);
    			if(a==b)continue;
    			fa[b]=a;
    			root[a]=Merge(root[a],root[b]);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    如何:为 Silverlight 客户端生成双工服务
    Microsoft Sync Framework 2.1 软件开发包 (SDK)
    Windows 下的安装phpMoAdmin
    asp.net安全检测工具 Padding Oracle 检测
    HTTP Basic Authentication for RESTFul Service
    Windows系统性能分析
    Windows Server AppFabric Management Pack for Operations Manager 2007
    Mongo Database 性能优化
    服务器未能识别 HTTP 标头 SOAPAction 的值
    TCP WAIT状态及其对繁忙的服务器的影响
  • 原文地址:https://www.cnblogs.com/sdzwyq/p/8636602.html
Copyright © 2011-2022 走看看