ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P3242 [HNOI2015] 接水果

2022-06-02 20:31:28  阅读:139  来源: 互联网

标签:水果 int ed top st ++ mp HNOI2015 P3242


P3242 [HNOI2015] 接水果

整体二分练手题。

考虑一条路径 \((x,y)\) 被另一条路径 \((u,v)\) 包含的本质。

考虑 dfs 序,设 \(st_x=dfn_x\),$$ed_x=dfn_x+siz_x-1$。

不妨设 \(st_x<st_y\)。

  • \(\operatorname{LCA}(x,y)=x\)

    则 \(u\in [1,st_z-1]\) 或 \(u \in[ed_z+1,n]\),\(v \in [st_y,ed_y]\),其中 \(z\) 为 \(x \to y\) 路径上 \(x\) 的第一个儿子。

  • \(LCA(x,y) \ne x\)

    则 \(u\in [st_x,ed_x]\),\(v \in [st_y,ed_y]\)。

由于题目查询第 \(k\) 大,考虑整体二分。

整体二分加扫描线,时间复杂度 \(\mathcal O(n \log^2 n)\),空间复杂度 \(\mathcal O(n)\)。

#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 >= '0' && c <= '9')
    {
        x = (x << 3) + (x << 1) + c - 48;
        c = getchar();
    }
    return x * f;
}

const int _ = 4e4 + 10;

int n, m, Q, B, ans[_];

int len, mp[_];

int tot, head[_], to[_ << 1], nxt[_ << 1];

inline void add(int u, int v)
{
	to[++tot] = v, nxt[tot] = head[u], head[u] = tot;
}

int cnt, dep[_], siz[_], fa[_], top[_], hson[_], st[_], ed[_];

struct Query
{
	int op, x, l, r, k, v, id;
} q[_ * 5], q1[_ * 5], q2[_ * 5];

inline bool cmp(Query a, Query b)
{
	if(a.x != b.x) return a.x < b.x;
	return a.op < b.op;
}

void dfs1(int u, int D = 1)
{
	dep[u] = D, siz[u] = 1;
	for(int i = head[u]; i; i = nxt[i])
	{
		int v = to[i];
		if(siz[v]) continue;
		fa[v] = u;
		dfs1(v, D + 1);
		siz[u] += siz[v];
		if(siz[hson[u]] < siz[v]) hson[u] = v;
	}
}

void dfs2(int u, int tf)
{
	top[u] = tf;
	st[u] = ++cnt;
	if(hson[u]) dfs2(hson[u], tf);
	for(int i = head[u]; i; i = nxt[i])
	{
		int v = to[i];
		if(top[v]) continue;
		dfs2(v, v);
	}
	ed[u] = cnt;
}

inline int LCA(int x, int y)
{
	while(top[x] != top[y])
	{
		if(dep[top[x]] < dep[top[y]]) swap(x, y);
		x = fa[top[x]];
	}
	return dep[x] > dep[y] ? y : x;
}

inline int get(int x, int y)
{
	while(top[x] != top[y])
	{
		if(fa[top[x]] == y) return top[x];
		x = fa[top[x]];
	}
	return hson[y];
}

int c[_];

inline void update(int x, int y)
{
	for(; x <= n; x += x & -x) c[x] += y;
}

inline int query(int x)
{
	int res = 0;
	for(; x; x -= x & -x) res += c[x];
	return res;
}

void solve(int L, int R, int l, int r)
{
	if(L > R) return;
	if(l == r)
	{
		for(int i = L; i <= R; ++i)
			if(q[i].op == 2) ans[q[i].id] = mp[l];
		return;
	}
	int mid = (l + r) >> 1, c1 = 0, c2 = 0, val;
	for(int i = L; i <= R; ++i)
		if(q[i].op == 1)
		{
			if(q[i].k <= mid)
			{
				update(q[i].l, q[i].v), update(q[i].r + 1, -q[i].v);
				q1[++c1] = q[i];
			}
			else q2[++c2] = q[i];
		}
		else
		{
			val = query(q[i].l);
			if(val >= q[i].k) q1[++c1] = q[i];
			else q[i].k -= val, q2[++c2] = q[i];
		}
	for(int i = 1; i <= c1; ++i) q[L + i - 1] = q1[i];
	for(int i = 1; i <= c2; ++i) q[L + i + c1 - 1] = q2[i];
	solve(L, L + c1 - 1, l, mid), solve(L + c1, R, mid + 1, r);
}

signed main()
{
	n = read(), m = read(), Q = read();
	for(int i = 1, x, y; i < n; ++i)
	{
		x = read(), y = read();
		add(x, y), add(y, x);
	}
	dfs1(1), dfs2(1, 1);
	for(int i = 1, x, y, z, k, lca; i <= m; ++i)
	{
		x = read(), y = read(), k = read();
		mp[i] = k;
		if(st[x] > st[y]) swap(x, y);
		lca = LCA(x, y);
		if(lca == x)
		{
			z = get(y, x);
			if(st[z] > 1)
			{
				q[++B] = {1, 1, st[y], ed[y], k, 1, 0};
				q[++B] = {1, st[z], st[y], ed[y], k, -1, 0};
			}
			if(ed[z] < n)
			{
				q[++B] = {1, st[y], ed[z] + 1, n, k, 1, 0};
				q[++B] = {1, ed[y] + 1, ed[z] + 1, n, k, -1, 0};
			}
		}
		else
		{
			q[++B] = {1, st[x], st[y], ed[y], k, 1, 0};
			q[++B] = {1, ed[x] + 1, st[y], ed[y], k, -1, 0};
		}
	}
	sort(mp + 1, mp + m + 1);
	len = unique(mp + 1, mp + m + 1) - mp - 1;
	for(int i = 1; i <= B; ++i) q[i].k = lower_bound(mp + 1, mp + len + 1, q[i].k) - mp;
	for(int i = 1, x, y, k; i <= Q; ++i)
	{
		x = read(), y = read(), k = read();
		if(st[x] > st[y]) swap(x, y);
		q[++B] = {2, st[x], st[y], 0, k, 0, i};
	}
	sort(q + 1, q + B + 1, cmp);
	solve(1, B, 1, len);
	for(int i = 1; i <= Q; ++i) printf("%d\n", ans[i]);
	return 0;
}

标签:水果,int,ed,top,st,++,mp,HNOI2015,P3242
来源: https://www.cnblogs.com/orzz/p/16338941.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有