zoukankan      html  css  js  c++  java
  • [BZOJ3545] [ONTAK2010]Peaks(线段树合并 + 离散化)

    传送门

    由于困难值小于等于x这个很恶心,可以离线处理,将边权,和询问时的x排序。

    每到一个询问的时候,将边权小于等于x的都合并起来再询问。

    。。

    有重复元素的线段树合并的时间复杂度是nlog^2n

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #define N 500001
    
    int n, m, q, cnt, tot, size;
    int sum[N * 10], ls[N * 10], rs[N * 10], a[N], b[N], f[N], root[N], ans[N], c[N << 1];
    
    struct node
    {
    	int x, y, z, id;
    	node(int x = 0, int y = 0, int z = 0, int id = 0) : x(x), y(y), z(z), id(id) {}
    }p[N], ask[N];
    
    inline int read()
    {
    	int x = 0, f = 1;
    	char ch = getchar();
    	for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
    	for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
    	return x * f;
    }
    
    inline bool cmp1(node x, node y)
    {
    	return x.z < y.z;
    }
    
    inline bool cmp2(node x, node y)
    {
    	return x.y < y.y;
    }
    
    inline void merge(int &x, int y)
    {
    	if(!x || !y)
    	{
    		x += y;
    		return;
    	}
    	sum[x] += sum[y];
    	merge(ls[x], ls[y]);
    	merge(rs[x], rs[y]);
    }
    
    inline void insert(int &now, int l, int r, int x)
    {
    	now = ++size;
    	if(l == r)
    	{
    		sum[now] = 1;
    		return;
    	}
    	int mid = (l + r) >> 1;
    	if(x <= mid) insert(ls[now], l, mid, x);
    	else insert(rs[now], mid + 1, r, x);
    	sum[now] = sum[ls[now]] + sum[rs[now]];
    }
    
    inline int query(int now, int l, int r, int x)
    {
    	if(l == r) return l;
    	int mid = (l + r) >> 1;
    	if(x <= sum[ls[now]])
    		return query(ls[now], l, mid, x);
    	else
    		return query(rs[now], mid + 1, r, x - sum[ls[now]]);
    }
    
    inline int find(int x)
    {
    	return x == f[x] ? x : f[x] = find(f[x]);
    }
    
    int main()
    {
    	int i, j, x, y, z;
    	n = read();
    	m = read();
    	q = read();
    	for(i = 1; i <= n; i++) a[i] = b[i] = read();
    	std::sort(b + 1, b + n + 1);
    	cnt = std::unique(b + 1, b + n + 1) - b - 1;
    	for(i = 1; i <= n; i++)
    	{
    		a[i] = std::lower_bound(b + 1, b + cnt + 1, a[i]) - b;
    		f[i] = i;
    		insert(root[i], 1, cnt, a[i]);
    	}
    	for(i = 1; i <= m; i++)
    	{
    		x = read();
    		y = read();
    		c[i] = z = read();
    		p[i] = node(x, y, z, 0);
    	}
    	for(i = 1; i <= q; i++)
    	{
    		x = read();
    		c[i + m] = y = read();
    		z = read();
    		ask[i] = node(x, y, z, i);
    	}
    	std::sort(c + 1, c + m + q + 1);
    	tot = std::unique(c + 1, c + m + q + 1) - c - 1;
    	for(i = 1; i <= m; i++)
    		p[i].z = std::lower_bound(c + 1, c + tot + 1, p[i].z) - c;
    	for(i = 1; i <= q; i++)
    		ask[i].y = std::lower_bound(c + 1, c + tot + 1, ask[i].y) - c;
    	std::sort(p + 1, p + m + 1, cmp1);
    	std::sort(ask + 1, ask + q + 1, cmp2);
    	j = 1;
    	for(i = 1; i <= q; i++)
    	{
    		while(j <= m && p[j].z <= ask[i].y)
    		{
    			x = find(p[j].x);
    			y = find(p[j].y);
    			if(x ^ y)
    			{
    				f[y] = x;
    				merge(root[x], root[y]);
    			}
    			j++;
    		}
    		x = find(ask[i].x);
    		if(ask[i].z > sum[root[x]]) ans[ask[i].id] = -1;
    		else ans[ask[i].id] = b[query(root[x], 1, cnt, sum[root[x]] - ask[i].z + 1)];
    	}
    	for(i = 1; i <= q; i++) printf("%d
    ", ans[i]);
    	return 0;
    }
    

      

  • 相关阅读:
    腾讯课堂——基础数据类型(dict字典)
    腾讯课堂——基础数据类型(tuple元祖)
    基础数据类型(list列表)
    第 018讲:函数:灵活即强大(关键字函数,默认函数,收集函数)
    第 015讲:字符串:格式化
    第 013讲: 元组tuple 上了枷锁的列表
    第 012讲:打了激素的数组3
    第 011讲:一个打了激素的数组[02]
    range函数的用法
    第 010讲:一个打了激素的数组[01]
  • 原文地址:https://www.cnblogs.com/zhenghaotian/p/7518804.html
Copyright © 2011-2022 走看看