• bzoj3545: [ONTAK2010]Peaks


    题目链接

    bzoj3545: [ONTAK2010]Peaks

    题解

    对于<=x的边集构成多个联通块,对于询问离线,维护单调递增的<=x的联通块,每次线段树合并,查询k大。

    代码

    /* 
    苟活者在淡红的血色中,会看见依稀的微茫  
    
    */ 
    
    #include<bits/stdc++.h> 
    using namespace std; 
    inline int read() { 
    	int x = 0,f = 1; 
    	char c = getchar(); 
    	while(c < '0' || c > '9') {if(c == '-')f =- 1; c = getchar();} 
    	while(c <= '9' && c >= '0')x = x * 10 + c - '0',c = getchar(); 
    	return x  * f; 
    }  
    const int maxn = 250007; 
    struct node { 
    	int u,v,w; 
    	bool operator < (const node & a) const { 
    		return w < a.w;  
    	}  
    } edge[(maxn << 1) + 7]; 
    struct Query { 
    	int u,v,k,id;   
    	bool operator < (const Query & a) const { 
    		return v < a.v; 
    	}	
    }q[maxn * 2] ; 
    #define lc son[x][0] 
    #define rc son[x][1] 
    int n,m,Q,cnt;  
    int h[maxn],ans[maxn * 2],sz[maxn * 20],son[maxn * 20][2],tot = 0; 
    void insert(int &x ,int l,int r,int rk) { 
    	sz[x = ++ tot] = 1; 
    	if(l == r) return ; 
    	int mid = l + r >> 1; 
    	if(rk <= mid) insert(lc,l,mid,rk); 
    	else insert(rc,mid + 1,r,rk); 
    } 
    int  Merge(int x,int y) { 
    	if(!x || !y) return x ^ y; 
    	lc = Merge(lc,son[y][0]);rc = Merge(rc,son[y][1]); 
    	sz[x] += sz[y];sz[y] = 0; return x; 
    }  
    int Query(int x,int l,int r,int k) { 
    	if(l == r) return l; 
    	int lz = sz[lc],mid = l + r >> 1; 
    	if(k <= lz) return Query(lc,l,mid,k); 
    	else return Query(rc,mid + 1,r,k - lz); 
    	
    } 
    int fa[maxn],ref[maxn]; 
    int find(int x ) { 
    	if(fa[x] != x)fa[x] = find(fa[x]); 
    	return fa[x];  
    } 
    int root[maxn * 15]; 
    void merge(int x,int y) { 
    	int r1 = find(x),r2 = find(y); 
    	if(r1 == r2) return; 
    	fa[r2] = r1,root[r1] = Merge(root[r1],root[r2]); 
    } 
    int query(int x,int k) { 
    	int rt = find(x); 
    	return sz[root[rt]] < k ? - 1 : ref[Query(root[rt],1,cnt,sz[root[rt]] - k + 1)]; 
    }     
    int main() { 
    	n = read(),m = read(),Q = read(); 
    	for(int i = 1;i <= n;++ i) ref[i] = h[i] = read(),fa[i] = i; 
    	std::sort(ref + 1, ref + n + 1),cnt = 1;
    	for(int i = 2;i <= n;++ i) if(ref[i] != ref[i - 1]) ref[++ cnt] = ref[i]; 
    	for(int i = 1;i <= n;++ i) insert(root[i],1,cnt,lower_bound(ref + 1,ref + cnt + 1,h[i]) - ref);  
    	for(int i = 1;i <= m;++ i) edge[i].u = read(),edge[i].v = read(), edge[i].w = read();
    	std::sort(edge + 1,edge + m + 1);  
    	for(int i = 1;i <= Q;++ i) 
    	  	q[i].u = read(),q[i].v = read(),q[i].k = read(),q[i].id = i;  
    	std::sort(q + 1,q + Q + 1); 
    	for(int i = 1,now = 1; i <= Q;++ i) { 
    	  	while(now <= m && edge[now].w <= q[i].v) merge(edge[now].u,edge[now].v),++ now; 
    	  	ans[q[i].id] = query(q[i].u,q[i].k); 
    	} 
    	for(int i = 1;i <= Q;++ i) printf("%d
    ",ans[i]); 
    	return 0; 	
    }     
    	
          
    
  • 相关阅读:
    c# GDI+中发生一般性错误的解决办法
    AutoMapper ProjectTo 与 Mapster ProjectToType
    c# 无法加载 DLL“SQLite.Interop.DLL”: 找不到指定的模块
    c# 剪裁图片
    c# System.InvalidOperationException:“在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke
    如何生成自己的二维码qrcode模块的使用
    Firefox20 到 Firefox21 的一个小改变
    修改document.domain的注意事项
    ✍59 300I显卡测试总结
    ✍57 PiPy上传模块&Linux 拆分合并
  • 原文地址:https://www.cnblogs.com/sssy/p/9354919.html
Copyright © 2020-2023  润新知