• 永无乡「HNOI2012」


    题意

    每个数有一个排名,要求维护两种操作:

    1. (x)(y)所在的联通块连载一起。

    2. 查询(x)所在联通块的(k)小值。


    思路

    思路显然,并查集维护连通性,动态开点权值线段树合并维护查询。这道题污染了HNOI。

    代码

    #include <bits/stdc++.h>
    
    using namespace std;
    
    namespace StandardIO {
    
    	template<typename T> inline void read (T &x) {
    		x=0;T f=1;char c=getchar();
    		for (; c<'0'||c>'9'; c=getchar()) if (c=='-') f=-1;
    		for (; c>='0'&&c<='9'; c=getchar()) x=x*10+c-'0';
    		x*=f;
    	}
    	template<typename T> inline void write (T x) {
    		if (x<0) putchar('-'),x=-x;
    		if (x>=10) write(x/10);
    		putchar(x%10+'0');
    	}
    
    }
    
    using namespace StandardIO;
    
    namespace Solve {
    	
    	const int N=100001;
    	
    	int n,m,q;
    	int val[N],trn[N];
    	int f[N];
    	int cnt;
    	struct node {
    		int lc,rc;
    		int l,r,val;
    	} tree[N*40];
    	int root[N];
    	
    	inline void pushup (int pos) {
    		tree[pos].val=tree[tree[pos].lc].val+tree[tree[pos].rc].val;
    	}
    	void build (int rt,int l,int r,int &pos) {
    		if (!pos) pos=++cnt; 
    		tree[pos].l=l,tree[pos].r=r,tree[pos].val=0;
    		if (l==r) return tree[pos].val=(l==val[rt]),void();
    		int mid=(l+r)>>1;
    		if (val[rt]<=mid) build(rt,l,mid,tree[pos].lc);
    		else build(rt,mid+1,r,tree[pos].rc);
    		pushup(pos);
    	}
    	int query (int k,int pos) {
    		if (tree[pos].l==tree[pos].r) return tree[pos].l;
    		if (k<=tree[tree[pos].lc].val) return query(k,tree[pos].lc);
    		return query(k-tree[tree[pos].lc].val,tree[pos].rc);
    	}
    	void Tmerge (int &x,int y) {
    		if (!x) return x=y,void();
    		if (!y) return;
    		if (tree[x].l==tree[x].r) return tree[x].val+=tree[y].val,void();
    		Tmerge(tree[x].lc,tree[y].lc),Tmerge(tree[x].rc,tree[y].rc);
    		pushup(x);
    	}
    	inline int find (int x) {
    		return (f[x]==x)?x:f[x]=find(f[x]);
    	}
    	inline void merge (int x,int y) {
    		x=find(x),y=find(y);
    		if (f[x]!=y) f[x]=y,Tmerge(root[y],root[x]);
    	}
    	void dfs (int now) {
    		cout<<tree[now].l<<' '<<tree[now].r<<endl;
    		if (tree[now].lc) cout<<"lc:",dfs(tree[now].lc);
    		if (tree[now].rc) cout<<"rc:",dfs(tree[now].rc);
    	}
    
    	inline void MAIN () {
    		read(n),read(m);
    		for (register int i=1; i<=n; ++i) {
    			read(val[i]),trn[val[i]]=i,f[i]=i,build(i,1,n,root[i]);
    		}
    		for (register int i=1; i<=m; ++i) {
    			int x,y;
    			read(x),read(y);
    			merge(x,y);
    		}
    		read(q);
    		while (q--) {
    			char op;int x,y;
    			cin>>op,read(x),read(y);
    			if (op=='B') {
    				merge(x,y);
    			} else {
    				if (tree[root[find(x)]].val<y) write(-1);
    				else write(trn[query(y,root[find(x)])]);
    				putchar('
    ');
    			}
    		}
    	}
    
    }
    
    int main () {
    	Solve::MAIN();
    }
    
  • 相关阅读:
    第十周课程总结
    第九周课程总结&实验报告(七)
    第八周课程总结和实验报告
    第六周作业
    第五周课程总结和实验报告
    第四周课程总结和实验报告
    课程总结
    第十四周
    第十三周学习总结
    第十二周总结
  • 原文地址:https://www.cnblogs.com/ilverene/p/11405510.html
Copyright © 2020-2023  润新知