• P3224 [HNOI2012]永无乡(线段树合并)


    支持加边和询问连通块第k大点权。

    线段树合并即可。

    //线段树合并
    //每次合并两个连通块的权值线段树
    //询问第k大 
    #include<bits/stdc++.h>
    using namespace std; 
    const int maxn=1e5+10;
    const int M=maxn*100;
    int c[M],lson[M],rson[M],T[maxn],tot;
    void pushup (int newRoot) {
    	c[newRoot]=c[lson[newRoot]]+c[rson[newRoot]];
    }
    int up (int i,int l,int r,int p,int v) {
    	int newRoot=i;
    	if (!newRoot) newRoot=++tot;
    	if (l==r) {
    		c[newRoot]+=v;
    		return newRoot;
    	}
    	int mid=(l+r)>>1;
    	if (p<=mid) lson[newRoot]=up(lson[newRoot],l,mid,p,v);
    	if (p>mid) rson[newRoot]=up(rson[newRoot],mid+1,r,p,v);
    	pushup(newRoot);
    	return newRoot;
    }
    int merge (int x,int y,int l,int r) {
    	if (!x) return y;
    	if (!y) return x;
    	if (l==r) {
    		c[x]+=c[y];
    		return x;
    	}
    	int mid=(l+r)>>1;
    	lson[x]=merge(lson[x],lson[y],l,mid);
    	rson[x]=merge(rson[x],rson[y],mid+1,r);
    	pushup(x);
    	return x; 
    }
    int kth (int u,int l,int r,int k) {
    	//在一颗权值树上找第k大
    	if (l==r) return l;
    	int mid=(l+r)>>1;
    	if (c[lson[u]]<k) {
    		return kth(rson[u],mid+1,r,k-c[lson[u]]);
    	} 
    	else {
    		return kth(lson[u],l,mid,k);
    	}
    }
    int father[maxn],n,m,sz[maxn];
    int findfather (int x) {
    	int a=x;
    	while (x!=father[x]) x=father[x];
    	while (a!=father[a]) {
    		int z=a;
    		a=father[a];
    		father[z]=x;
    	} 
    	return x;
    }
    int p[maxn];
    int b[maxn];
    int main () {
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;i++) father[i]=i,sz[i]=1;
    	for (int i=1;i<=n;i++) scanf("%d",p+i),b[p[i]]=i;
    	for (int i=1;i<=n;i++) T[i]=up(T[i],1,n,p[i],1);
    	while (m--) {
    		int x,y;
    		scanf("%d%d",&x,&y);
    		x=findfather(x);
    		y=findfather(y);
    		if (x==y) continue;
    		father[x]=y;
    		sz[y]+=sz[x];
    		T[y]=merge(T[y],T[x],1,n);
    	} 
    	int q;
    	scanf("%d",&q);
    	while (q--) {
    		string op;
    		cin>>op;
    		if (op=="Q") {
    			int x,y;
    			scanf("%d%d",&x,&y);
    			x=findfather(x);
    			if (y>sz[x]) printf("-1
    ");
    			else printf("%d
    ",b[kth(T[x],1,n,y)]);
    		}
    		else {
    			int x,y;
    			scanf("%d%d",&x,&y);
    			x=findfather(x);
    			y=findfather(y);
    			if (x==y) continue;
    			father[x]=y;
    			sz[y]+=sz[x];
    			T[y]=merge(T[y],T[x],1,n);
    		}
    	}
    }
  • 相关阅读:
    Path Sum
    Linked List Cycle II
    Linked List Cycle
    Single Number i and ii
    Binary Tree Preorder Traversal and Binary Tree Postorder Traversal
    Max Points on a Line
    Evaluate Reverse Polish Notation
    【leetcode】98 验证二叉搜索树
    【vivo2020春招】 02 数位之积
    【vivo2020春招】03 vivo智能手机产能
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/15110090.html
Copyright © 2020-2023  润新知