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

    题面

    一开始,每个集合只有一个岛,对于一个集合,我们建一棵线段树,当连边的时候,我们先判断一下是不是已经在一个集合,然后合并线段树,查询的时候查询所在集合的线段树即可,若(k)大于集合元素数,输出(-1)

    那么怎么维护集合呢?并查集啊

    做完了

    下面是代码

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cctype>
    #define ll long long
    #define gc getchar
    #define maxn 100005
    using namespace std;
    
    inline ll read(){
    	ll a=0;int f=0;char p=gc();
    	while(!isdigit(p)){f|=p=='-';p=gc();}
    	while(isdigit(p)){a=(a<<3)+(a<<1)+(p^48);p=gc();}
    	return f?-a:a;
    }int n,m,q,a[maxn],c[maxn];
    
    int f[maxn],sz[maxn];
    int find(int i){
    	if(f[i]!=i)f[i]=find(f[i]);
    	return f[i];
    }
    
    struct ahaha{
    	int v,ch[2];
    }t[maxn*40];int top,rt[maxn];
    #define lc t[i].ch[0]
    #define rc t[i].ch[1]
    void update(int &i,int l,int r,int k){
    	if(!i)i=++top;++t[i].v;
    	if(l==r)return;
    	int m=l+r>>1;
    	if(k<=m)update(lc,l,m,k);
    	else update(rc,m+1,r,k);
    }
    int query(int i,int l,int r,int k){
    	if(l==r)return c[l];
    	int m=l+r>>1,v=t[lc].v;
    	if(k<=v)return query(lc,l,m,k);
    	else return query(rc,m+1,r,k-v);
    }
    int merge(int x,int y){
    	if(!x||!y)return x+y;
    	int i=++top;t[i].v=t[x].v+t[y].v;
    	lc=merge(t[x].ch[0],t[y].ch[0]);
    	rc=merge(t[x].ch[1],t[y].ch[1]);
    	return i;
    }
    
    inline void solve_1(){
    	int x=read(),y=read();
    	int fx=find(x),fy=find(y);
    	if(fx==fy)return;
    	f[fy]=fx,sz[fx]+=sz[fy];
    	rt[fx]=merge(rt[fx],rt[fy]);
    }
    inline void solve_2(){
    	int x=read(),k=read();
    	int fx=find(x);
    	if(sz[fx]<k){
    		puts("-1");
    		return;
    	}
    	printf("%d
    ",query(rt[fx],1,n,k));
    }
    
    char s[5];
    int main(){
    	n=read();m=read();
    	for(int i=1;i<=n;++i){
    		a[i]=read(),f[i]=i,sz[i]=1;c[a[i]]=i;
    		update(rt[i],1,n,a[i]);
    	}
    	for(int i=1;i<=m;++i)
    		solve_1();
    	q=read();
    	while(q--){
    		scanf("%s",s+1);
    		switch(s[1]){
    			case 'B':solve_1();break;
    			case 'Q':solve_2();break;
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    用GDB调试程序(一)
    ZOJ Problem Set
    android 去除标题
    【hadoop之翊】——基于CentOS的hadoop2.4.0伪分布安装配置
    layoutSubviews总结
    用数据说话,外贸产品选择(中篇)-google趋势分析法
    Apache介绍
    浅谈android4.0开发之GridLayout布局
    Android GridView 分页加载数据
    Android TableLayout中的使用说明
  • 原文地址:https://www.cnblogs.com/hanruyun/p/10429618.html
Copyright © 2011-2022 走看看