• peaks


    给定一个无向图,点有点权边有边权

    Q次询问,每次询问从点v开始只经过边权<=x的边能到达所有点中点权第k大值,无解输出-1

    N<=1e5,M,Q<=5e5

    建立大根kruskal重构树,每次在重构树上倍增跳父亲,跳到最浅的边权<=x的父亲

    将kruskal所有叶子节点按照dfn的顺序建立一个序列,然后每次查询相当于序列区间第k大,显然可以用主席树维护

    代码里为了方便只给叶子节点赋了dfn,kruskal重构树每个节点记录dfn表示他所有儿子中dfn的最小的那个,记录sz表示叶子数量

    然后代码写得乱七八糟凑合着看吧

    注意kruskal重构树倍增范围是所有的节点(2*n-1)不是n!!!

    #include <bits/stdc++.h>
    using namespace std;
    
    struct edge
    {
    	int u, v, w;
    } a[500010];
    
    int n, m, q;
    int h[200010], dfn[200010], dfntot;
    int fa[200010][19], ds[200010], lch[200010], rch[200010], sz[200010], tmp[200010];
    int val[100010];
    int disc[100010];
    
    int sb;
    int root[100010];
    
    int tree[8000010], l[8000010], r[8000010], tot;
    
    int build_tree(int cl, int cr)
    {
    	tree[++tot] = 0;
    	if (cl < cr)
    	{
    		int mid = (cl + cr) / 2;
    		l[tot] = build_tree(cl, mid);
    		r[tot] = build_tree(mid + 1, cr);
    	}
    	return tot;
    }
    
    int newtree(int oldtree, int cl, int cr, int key)
    {
    	int p = ++tot;
    	l[p] = l[oldtree];
    	r[p] = r[oldtree];
    	tree[p] = tree[oldtree] + 1;
    	if (cl < cr)
    	{
    		if (key > (cl + cr) / 2)
    			r[p] = newtree(r[oldtree], (cl + cr) / 2 + 1, cr, key);
    		else
    			l[p] = newtree(l[oldtree], cl, (cl + cr) / 2, key);
    	}
    	return p;
    }
    
    int query(int tree2, int tree1, int cl, int cr, int key)
    {
    	if (cl >= cr)
    		return cl;
    	int sz = tree[l[tree2]] - tree[l[tree1]];
    	if (sz >= key)
    		return query(l[tree2], l[tree1], cl, (cl + cr) / 2, key);
    	else
    		return query(r[tree2], r[tree1], (cl + cr) / 2 + 1, cr, key - sz);
    }
    
    void jianshu()
    {
    	root[0] = build_tree(1, sb);
    	for (int i = 1; i <= n; i++)
    		root[i] = newtree(root[i - 1], 1, sb, val[i]);
    }
    
    int kth(int l, int r, int k)
    {
    	return query(root[r], root[l - 1], 1, sb, r - l + 2 - k);
    	return 233;
    }
    
    int getf(int x)
    {
    	return ds[x] == x ? x : ds[x] = getf(ds[x]);
    }
    
    void dfs(int x)
    {
    	if (x <= n)
    	{
    		dfn[x] = ++dfntot;
    		sz[x] = 1;
    		val[dfn[x]] = h[x];
    		return;
    	}
    	dfs(lch[x]);
    	dfs(rch[x]);
    	dfn[x] = dfn[lch[x]];
    	sz[x] = sz[lch[x]] + sz[rch[x]];
    }
    
    int main()
    {
    	scanf("%d%d%d", &n, &m, &q);
    	for (int i = 1; i <= n; i++)
    		scanf("%d", &h[i]);
    	for (int i = 1; i <= m; i++)
    		scanf("%d%d%d", &a[i].u, &a[i].v, &a[i].w);
    	sort(a + 1, a + 1 + m, [](const edge &a, const edge &b) {return a.w < b.w;});
    	for (int i = 1; i <= n; i++)
    		ds[i] = i;
    	int tot = n;
    	for (int i = 1; i <= m; i++)
    	{
    		if (getf(a[i].u) != getf(a[i].v))
    		{
    			int p = ++tot, p1 = getf(a[i].u), p2 = getf(a[i].v);
    			tmp[p] = a[i].w;
    			ds[p1] = ds[p2] = ds[p] = p;
    			fa[p1][0] = fa[p2][0] = p;
    			lch[p] = p1;
    			rch[p] = p2;
    		}
    	}
    	dfs(tot);
    	for (int j = 1; j <= 18; j++)
    		for (int i = 1; i <= tot; i++)
    			fa[i][j] = fa[fa[i][j - 1]][j - 1];
    	// for (int i = 1; i <= n; i++)
    		// printf("%d%c", val[i], i == n ? '
    ' : ' ');
    	tmp[0] = 0x3f3f3f3f;
    	for (int i = 1; i <= n; i++)
    		disc[i] = val[i];
    	sort(disc + 1, disc + 1 + n);
    	sb = unique(disc + 1, disc + 1 + n) - disc - 1;
    	for (int i = 1; i <= n; i++)
    		val[i] = lower_bound(disc + 1, disc + 1 + sb, val[i]) - disc;
    	// for (int i = 1; i <= n; i++)
    		// printf("%d%c", val[i], i == n ? '
    ' : ' ');
    	jianshu();
    	for(int i = 1; i <= q; i++)
    	{
    		int v, x, k;
    		scanf("%d%d%d", &v, &x, &k);
    		for (int j = 18; j >= 0; j--)
    			if (tmp[fa[v][j]] <= x)
    				v = fa[v][j];
    		if (sz[v] < k)
    			puts("-1");
    		else
    			printf("%d
    ", disc[kth(dfn[v], dfn[v] + sz[v] - 1, k)]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    css3多列
    伪元素
    text文本样式二
    透明登录框
    透明度设置opacity
    超链接
    meta标签
    奇偶选择器
    OC跟Swift混编
    Swift中as as! as?的区别
  • 原文地址:https://www.cnblogs.com/oier/p/10231295.html
Copyright © 2020-2023  润新知