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

    题目地址


    基本思路:

    • 权值线段树+线段树合并+并查集. 

    类似题目:

    • 雨天的尾巴

    #include<cstdio>
    #include<iostream>
    using namespace std;
    const int MAXN=1e7,INF=2e9;
    struct Node{
    	int ls,rs;
    	int cnt;//被加次数 
    	int pos;//岛屿编号 
    }tr[MAXN];
    int nodeCnt=0;//权值线段树 
    int root[MAXN];
    void insert(int &now,int l,int r,int x,int pos){
    	if(!now)now=++nodeCnt;
    	if(l==r){
    		tr[now].cnt++;
    		tr[now].pos=pos;
    		return;
    	}
    	int mid=(l+r)>>1;
    	if(x<=mid)insert(tr[now].ls,l,mid,x,pos);
    	else insert(tr[now].rs,mid+1,r,x,pos);
    	tr[now].cnt=tr[tr[now].ls].cnt+tr[tr[now].rs].cnt;
    }
    int merge(int p,int q,int l,int r){
    	if(!p)return q;
    	if(!q)return p;
    	if(l==r){
    		tr[p].cnt+=tr[q].cnt;
    		tr[p].pos=tr[q].pos;
    		return p;
    	}
    	int mid=(l+r)>>1;
    	tr[p].ls=merge(tr[p].ls,tr[q].ls,l,mid);
    	tr[p].rs=merge(tr[p].rs,tr[q].rs,mid+1,r);
    	tr[p].cnt=tr[tr[p].ls].cnt+tr[tr[p].rs].cnt;
    	return p;
    }
    int query(int now,int l,int r,int k){
    	if(l==r)return tr[now].pos;
    	if(tr[now].cnt<k)return -1;//不存在 
    	int mid=(l+r)>>1;
    	int lsum=tr[tr[now].ls].cnt;
    	if(k<=lsum)return query(tr[now].ls,l,mid,k);
    	else return query(tr[now].rs,mid+1,r,k-lsum);
    }
    int fa[MAXN];
    int get(int x){
    	while(x!=fa[x])x=fa[x]=fa[fa[x]];
    	return x;
    }
    int b_merge(int a,int b){//集合合并 
    	fa[get(a)]=get(b);
    	return get(b);
    }
    int main(){
    	int n,m;
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++)
    		fa[i]=i;
    	for(int i=1;i<=n;i++){
    		int rank;//重要度 
    		scanf("%d",&rank);
    		insert(root[i],-INF,INF,rank,i);
    	}
    	for(int i=1;i<=m;i++){
    		int a,b;
    		scanf("%d%d",&a,&b);
    		a=get(a),b=get(b);
    		int rt=merge(root[a],root[b],-INF,INF);
    		b_merge(a,b);
    		root[a]=root[b]=rt;
    	}
    	int q;
    	scanf("%d",&q);//q个操作
    	for(int i=1;i<=q;i++){
    		char opt;
    		cin>>opt;
    		if(opt=='B'){
    			int x,y;
    			scanf("%d%d",&x,&y);//修一条新桥 
    			x=get(x),y=get(y);
    			int rt=merge(root[x],root[y],-INF,INF);
    			b_merge(x,y);
    			root[x]=root[y]=rt;
    		}else if(opt=='Q'){
    			int x,k;
    			scanf("%d%d",&x,&k);
    			cout<<query(root[get(x)],-INF,INF,k)<<endl; 
    		}
    	} 
    	return 0;
    }
    

      

  • 相关阅读:
    gitlab 搭建(基于现有nginx)
    CENTOS 7平滑升级PHP到最新版7.3
    zabbix 5.0安装
    禅道 基于原lnmp 搭建
    mysql5.5升级至5.7 或升级至8.0
    gitlab搭建
    Autoboxing an autounboxing in genral
    java concurrency
    Why use interface type to declare a collectio
    Java coding style
  • 原文地址:https://www.cnblogs.com/zbsy-wwx/p/11747721.html
Copyright © 2011-2022 走看看