• BZOJ2733: [HNOI2012]永无乡


    BZOJ2733: [HNOI2012]永无乡


    题目描述

    传送门

    题目分析

    题目要求合并集合和查询某个集合中的第(k)大,发现线段树合并可以做。

    又有一个非常好的性质,一个权值对应唯一的一个位置,所以在权值线段树上直接在相应权值打上标记,查询的时候直接查询到底,合并直接上线段树合并,就可以了。

    是代码呢

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN=1e5+7;
    #define mid ((l+r)>>1)
    int f[MAXN],st[MAXN<<5],L[MAXN<<5],R[MAXN<<5],T[MAXN],n,m,fa[MAXN<<5],sz,a[MAXN],q;
    char opt[2];
    inline int read()
    {
        int x=0,c=1;
        char ch=' ';
        while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
        while(ch=='-')c*=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*c;
    }
    inline int find(int x) {return f[x]==x?f[x]:f[x]=find(f[x]);}
    inline int query(int x,int k)
    {
    	if(st[x]<k) return -1;
    	if(st[x]==k) return fa[x];
    	if(st[L[x]]<k) return query(R[x],k-st[L[x]]);
    	else return query(L[x],k);
    }
    inline int query(int x,int l,int r,int k)
    {
    	if(st[x]<k) return -1;
    	if(l==r) return fa[x];
    	if(st[L[x]]<k) return query(R[x],mid+1,r,k-st[L[x]]);
    	else return query(L[x],l,mid,k);
    }
    inline void modify(int &u,int l,int r,int k,int x)
    {
    	if(!u) u=++sz;
    	if(l==r){
    		st[u]++;fa[u]=x;
    		return;
    	}
    	if(mid>=k) modify(L[u],l,mid,k,x);
    	else modify(R[u],mid+1,r,k,x);
    	st[u]=st[L[u]]+st[R[u]];
    //	if(!R[u]) fa[u]=fa[L[u]];else fa[u]=fa[R[u]];
    }
    inline void merge(int &u,int v)
    {
    	if(!u||!v){u+=v;return;}
    	st[u]+=st[v];
    	merge(L[u],L[v]);merge(R[u],R[v]);
    }
    int main()
    {
    	n=read();m=read();
    	for(int i=1;i<=n;i++) a[i]=read(),f[i]=i;
    	for(int i=1;i<=n;i++) modify(T[i],1,n,a[i],i);
    	for(int i=1;i<=m;i++){
    		int x=read(),y=read();
    		int r1=find(x),r2=find(y);
    		if(r1==r2) continue;
    		f[r2]=r1;
    		merge(T[r1],T[r2]);
    	}
    	q=read();
    	while(q--){
    		scanf("%s",opt);
    		int x=read(),y=read();
    		if(opt[0]=='B'){
    			int r1=find(x),r2=find(y);
    			if(r1==r2) continue;
    			f[r2]=r1;
    			merge(T[r1],T[r2]);
    		} else {
    			int d=find(x);
    			printf("%d
    ",query(T[d],1,n,y));
    		}
    	}
    }
    
  • 相关阅读:
    Dbcp2抛出org.apache.commons.dbcp2.LifetimeExceededException
    DbUtils使用时抛出Cannot get a connection
    Spring注解【非单例】
    Exception in thread java.lang.IllegalThreadStateException
    eclipse选中变量,相同变量高亮。
    git push 403
    java虚拟机能并发的启动多少个线程
    产品的随想
    【转载】学习新东西的唯一方法
    Mysql错误问题记录
  • 原文地址:https://www.cnblogs.com/victorique/p/10556693.html
Copyright © 2020-2023  润新知