zoukankan      html  css  js  c++  java
  • 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; 	
    }     
    	
          
    
  • 相关阅读:
    BZOJ 3506 机械排序臂 splay
    BZOJ 2843 LCT
    BZOJ 3669 魔法森林
    BZOJ 2049 LCT
    BZOJ 3223 文艺平衡树 splay
    BZOJ 1433 假期的宿舍 二分图匹配
    BZOJ 1051 受欢迎的牛 强连通块
    BZOJ 1503 郁闷的出纳员 treap
    BZOJ 1096 ZJOI2007 仓库设计 斜率优化dp
    BZOJ 1396: 识别子串( 后缀数组 + 线段树 )
  • 原文地址:https://www.cnblogs.com/sssy/p/9354919.html
Copyright © 2011-2022 走看看