Codeforces Round #326 (Div. 1) C - Duff in the Army

Posted lordxx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #326 (Div. 1) C - Duff in the Army相关的知识,希望对你有一定的参考价值。

树上主席树。
题意要求求u-v的路径上,前k小个数字是多少。转换一下,每次求1-k小的数字。故我们想到了树上主席树。
基于树上点前缀和的特点有:(sum[u]+sum[v]-sum[lca]-sum[fa[lca]])是u-v路径的和。我们基于此,使用主席树,每个子树是权值线段树。就可以使用前缀和的思想来求得第k小。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#include <iomanip>
#pragma GCC optimize(2)
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
	char ch = getchar(); ll x = 0, f = 1;
	while (ch<‘0‘ || ch>‘9‘) { if (ch == ‘-‘)f = -1; ch = getchar(); }
	while (ch >= ‘0‘ && ch <= ‘9‘) { x = x * 10 + ch - ‘0‘; ch = getchar(); }
	return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
int n, m, q;
const int N = 1e5 + 10;
vector<int>vec[N];
vector<int>val[N];
int dp[2 * N][30];
int dep[N * 2];
int root[N];
int ver[2 * N];
int cnt = 0;
int par[N];
int rk[N];
struct zx {
	int tot;
	int tree[N * 20];
	int ls[N * 20];
	int rs[N * 20];
	void update(int &o, int pre, int l, int r, int pos)
	{
		o = ++tot;
		ls[o] = ls[pre], rs[o] = rs[pre];
		tree[o] = tree[pre] + 1;
		if (l == r)return;
		int mid = (l + r) >> 1;
		if (pos <= mid)update(ls[o], ls[pre], l, mid, pos);
		else update(rs[o], rs[pre], mid + 1, r, pos);
	}
	int query(int lca,int flca,int L,int R, int l, int r, int k)
	{
		if (tree[L] + tree[R] - tree[lca] - tree[flca] < k)return -1;
		if (l == r)return l;
		int mid = (l + r) >> 1;
		int temp = tree[ls[L]] + tree[ls[R]] - tree[ls[lca]] - tree[ls[flca]];
		if (k <= temp)return query(ls[lca], ls[flca], ls[L], ls[R], l, mid, k);
		else return query(rs[lca], rs[flca], rs[L], rs[R], mid + 1, r, k - temp);
	}
}T;
void dfs(int u, int fa,int d)
{
	ver[++cnt] = u;
	dep[cnt] = d;
	rk[u] = cnt;
	root[u] = root[fa];
	par[u] = fa;
	for (auto k : val[u])
	{
		T.update(root[u], root[u], 1, m, k);
	}
	for (auto k : vec[u])
	{
		if (k == fa)continue;
		dfs(k, u, d + 1);
		ver[++cnt] = u;
		dep[cnt] = d;
	}
}
void init()
{
	upd(i, 0, cnt)dp[i][0] = i;
	for (int j = 1; j <= 30; j++)
	{
		for (int i = 1; i + (1 << j) - 1 <= 2 * n; i++)
		{
			int t1 = dp[i][j - 1];
			int t2 = dp[i + (1 << (j - 1))][j - 1];
			dp[i][j] = dep[t1] > dep[t2] ? t2 : t1;
		}
	}
}
int stquery(int l, int r)
{
	l = rk[l], r = rk[r];
	if (l > r)swap(l, r);
	int k = int(log2(r - l + 1));
	int t1 = dp[l][k];
	int t2 = dp[r - (1 << k) + 1][k];
	return dep[t1] < dep[t2] ? ver[t1] : ver[t2];
}
int main()
{
	n = read(), m = read(), q = read();
	int u, v;
	upd(i, 1, n - 1)
	{
		u = read(), v = read();
		vec[u].push_back(v);
		vec[v].push_back(u);
	}
	upd(i, 1, m)
	{
		u = read();
		val[u].push_back(i);
	}
	dfs(1, 0, 1);
	init();
	int p;
	while (q--)
	{
		u = read(), v = read(), p = read();
		int lca = stquery(u, v);
		int flca = par[lca];
		vector<int>ans;
		upd(i, 1, p)
		{
			int temp = T.query(root[lca], root[flca], root[u], root[v], 1, m, i);
			if (temp == -1)break;
			ans.push_back(temp);
		}
		printf("%d ", ans.size());
		for (auto k : ans)
		{
			printf("%d ", k);
		}	
		printf("
");
	}
	return 0;
}


以上是关于Codeforces Round #326 (Div. 1) C - Duff in the Army的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #326 (Div. 2)-Duff and Meat

Codeforces Round #326 (Div. 1) B - Duff in Beach

Codeforces Round #326 (Div. 1) C - Duff in the Army

Codeforces Round #436 E. Fire(背包dp+输出路径)

[ACM]Codeforces Round #534 (Div. 2)

Codeforces Round #726 (Div. 2) B. Bad Boy(贪心)