zoukankan      html  css  js  c++  java
  • 【bzoj2733】 HNOI2012—永无乡

    http://www.lydsy.com/JudgeOnline/problem.php?id=2733 (题目链接)

    题意

      给出图上$n$个点,每个点有一个点权,每次询问一个连通块中点权第$K$小的点是谁,或者连接两个点。

    Solution

      权值线段树合并。

    细节

      也许会有负数?

    代码

    // bzoj2733
    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #define LL long long
    #define lim 1000000000
    #define inf 2147483640
    #define Pi acos(-1.0)
    #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout)
    using namespace std;
    
    const int maxn=100010;
    int n,m,Q,sz,rt[maxn],fa[maxn],size[maxn];
    struct node {
    	int son[2],s,id;
    	int& operator [] (int x) {return son[x];}
    }tr[maxn*40];
    
    namespace Segtree {
    	void build(int &k,int l,int r,int val,int id) {
    		if (!k) k=++sz;
    		if (l==r) {tr[k].s=1;tr[k].id=id;return;}
    		int mid=(l+r)>>1;
    		if (val<=mid) build(tr[k][0],l,mid,val,id);
    		else build(tr[k][1],mid+1,r,val,id);
    		tr[k].s=tr[tr[k][0]].s+tr[tr[k][1]].s;
    	}
    	int merge(int u,int v) {
    		if (!u || !v) return u|v;
    		tr[u][0]=merge(tr[u][0],tr[v][0]);
    		tr[u][1]=merge(tr[u][1],tr[v][1]);
    		tr[u].s=tr[tr[u][0]].s+tr[tr[u][1]].s;
    		return u;
    	}
    	int query(int u,int l,int r,int k) {
    		if (l==r) return tr[u].id;
    		int mid=(l+r)>>1,c=tr[tr[u][0]].s;
    		if (c>=k) return query(tr[u][0],l,mid,k);
    		else return query(tr[u][1],mid+1,r,k-c);
    	}
    }
    using namespace Segtree;
    
    int find(int x) {
    	return x==fa[x] ? x : fa[x]=find(fa[x]);
    }
    int main() {
    	scanf("%d%d",&n,&m);
    	for (int x,i=1;i<=n;i++) {
    		scanf("%d",&x);fa[i]=i;size[i]=1;
    		build(rt[i],-lim,lim,x,i);
    	}
    	for (int u,v,i=1;i<=m;i++) {
    		scanf("%d%d",&u,&v);
    		u=find(u),v=find(v);
    		if (size[u]<size[v]) swap(u,v);
    		fa[v]=u;size[u]+=size[v];
    		rt[u]=merge(rt[u],rt[v]);
    	}
    	scanf("%d",&Q);char ch[10];
    	for (int x,y,i=1;i<=Q;i++) {
    		scanf("%s%d%d",ch,&x,&y);
    		if (ch[0]=='Q') {
    			x=find(x);
    			printf("%d
    ",size[x]<y ? -1 : query(rt[x],-lim,lim,y));
    		}
    		if (ch[0]=='B') {
    			x=find(x),y=find(y);
    			if (x!=y) {
    				if (size[x]<size[y]) swap(x,y);
    				fa[y]=x;size[x]+=size[y];
    				rt[x]=merge(rt[x],rt[y]);
    			}
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    一行代码更改博客园皮肤
    fatal: refusing to merge unrelated histories
    使用 netcat 传输大文件
    linux 命令后台运行
    .net core 使用 Nlog 配置文件
    .net core 使用 Nlog 集成 exceptionless 配置文件
    Mysql不同字符串格式的连表查询
    Mongodb between 时间范围
    VS Code 使用 Debugger for Chrome 调试vue
    css权重说明
  • 原文地址:https://www.cnblogs.com/MashiroSky/p/6482610.html
Copyright © 2011-2022 走看看