首页 > 其他分享 >Codeforces Round 915 (div2) E

Codeforces Round 915 (div2) E

时间:2023-12-26 16:36:39浏览次数:29  
标签:sz int Codeforces id dfn 915 div2 change define

E. Tree Queries

[题目链接](https://codeforces.com/contest/1904/problem/EProblem - E - Codeforces)

题意概括:

给定一棵大小为 \(n\) 的树,回答如下询问,询问之间相互独立:

  • 给定一个点 \(x\) 与 \(k\) 个点 \(a_i\),求出从 \(x\) 出发不经过任何一个 \(a_i\) 的最长简单路径长度。

\(n,\sum k\le 2\times 10^5\)。

translated by cnyz.

重点思想:

一个点的子树一定是 dfn 上一段区间,用线段树对 dfn 序的深度序列维护,边 dfs 边左类似于“换根”的操作,在线段树上实时维护,对于询问讨论是否是当前点的父亲,进行做出改变。

标程:

#include <bits/stdc++.h>
using namespace std;
#define rep(i,l,r) for (int i = (l); i <= (r); i++)
#define per(i,r,l) for (int i = (r); i >= (l); i--)
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
#define maxn(a, b) a = max(a, b)
#define minn(a, b) a = min(a, b)
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
typedef double db;
const ll mod = 998244353;
mt19937 gen(114514);
ll rp(ll a,ll b) {ll res=1%mod;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}

const int inf = 1611243;
template <class T>
struct segtree {
	#define ls id + id
	#define rs id + id + 1
	int size;
	vector<T> mx, lz;

	void init(int n) {
		size = n;
		mx.clear(); lz.clear();
		mx.resize(n<<2);
		lz.resize(n<<2);
	}

	void pushdown(int id) {
		if (lz[id]) {
			mx[ls] += lz[id];
			mx[rs] += lz[id];
			lz[ls] += lz[id];
			lz[rs] += lz[id];
			lz[id] = 0;
		}
	}

	void change(int id, int l, int r, int x, int y, T v) {
		if (x <= l && r <= y) {
			mx[id] += v;
			lz[id] += v;
			return;
		}
		pushdown(id);
		int mid = (l + r) >> 1;
		if (x <= mid) change(ls, l, mid, x, y, v);
		if (y > mid) change(rs, mid + 1, r, x, y, v);
		mx[id] = max(mx[ls], mx[rs]);
	}

	T query(int id, int l, int r, int x, int y) {
		if (x <= l && r <= y)
			return mx[id];
		pushdown(id);
		int mid = (l + r) >> 1;
		T res = 0;
		if (x <= mid) res += query(ls, l, mid, x, y);
		if (y > mid) res += query(rs, mid + 1, r, x, y);
		return res;
	}

	T query(int l, int r) {
		assert(l <= r);
		return query(1, 1, size, l, r);
	}

	void change(int l, int r, T v) {
		if (l > r) return ;
		return change(1, 1, size, l, r, v);
	}
};
segtree<ll> t;
const int N = 200010;
int n, tim;
int ans[N], dfn[N], sz[N], go[N];
VI e[N], no[N], qe[N];

void dfs(int u, int fa, int dep) {
	dfn[u] = ++tim;
	sz[u] = 1;
	t.change(tim, tim, dep);
	for (auto v : e[u]) {
		if (v == fa) continue;
		dfs(v, u, dep + 1);
		sz[u] += sz[v];
	}
}

set<int> stk;

void getans(int u, int fa) {
	stk.insert(u);
	for (auto v : e[u]) {
		if (v == fa) continue;
		t.change(dfn[v], dfn[v] + sz[v] - 1, -1);
		t.change(1, dfn[v] - 1, 1);
		t.change(dfn[v] + sz[v], n, 1);
		go[u] = v;
		getans(v, u);
		t.change(dfn[v], dfn[v] + sz[v] - 1, 1);
		t.change(1, dfn[v] - 1, -1);
		t.change(dfn[v] + sz[v], n, -1);
	}
	for (auto id : qe[u]) {
		for (auto x : no[id]) {
			if (stk.count(x)) {
				t.change(1, dfn[go[x]] - 1, -inf);
				t.change(dfn[go[x]] + sz[go[x]], n, -inf);
			} else {
				t.change(dfn[x], dfn[x] + sz[x] - 1, -inf);
			}
		}
		ans[id] = t.mx[1];
		for (auto x : no[id]) {
			if (stk.count(x)) {
				t.change(1, dfn[go[x]] - 1, inf);
				t.change(dfn[go[x]] + sz[go[x]], n, inf);
			} else {
				t.change(dfn[x], dfn[x] + sz[x] - 1, inf);
			}
		}
	}
	stk.erase(u);
}

int main() {
	int q;
	scanf("%d%d", &n, &q);
	t.init(n);
	rep(i,2,n) {
		int u, v;
		scanf("%d%d", &u, &v);
		e[u].pb(v);
		e[v].pb(u);
	}

	VI id(n + 1);
	dfs(1, 0, 0);
	rep(i,1,n) id[dfn[i]] = i;

	rep(i,1,q) {
		int k, x;
		scanf("%d%d", &x, &k);
		no[i].resize(k);
		qe[x].pb(i);
		for (auto &x : no[i]) scanf("%d", &x);
	}

	getans(1, 0);

	rep(i,1,q) {
		printf("%d\n", ans[i]);
	}
	return 0;
}

标签:sz,int,Codeforces,id,dfn,915,div2,change,define
From: https://www.cnblogs.com/weirdoX/p/17928403.html

相关文章

  • codeforces刷题(1100):1917B_div2
    模板B、EraseFirstorSecondLetter跳转原题点击此:该题地址1、题目大意  给你一个字符串,可以执行任意次以下操作,生成最终的字符串(不可为空),问你能生成的不重复字符串数为多少。操作一:删除字符串第一个字符;操作二:删除字符串第二个字符。2、题目解析  发现,操作一:即选......
  • Codeforces 1909G - Pumping Lemma
    这个题思考角度很多,做法也很多。这里介绍一种@asmend和我讲的做法。设\(d=m-n\),那么我们枚举\(|x|=i,|y|=j\),设\(s,t\)的LCP长为\(l_1\),LCS长为\(l_2\),那么可以得到这组\((i,j)\)合法的充要条件是:\(i\lel_1\)\(m-i-j-d\lel_2\)。\(d\bmodj=0\)。\(t[i,i+d-1......
  • Codeforces1917F - Construct Tree
    Codeforces1917F-ConstructTreeProblems给一个长度为\(n\)的序列\(l\)和\(d\)。要求判断是否可以构造出一颗节点数为\(n+1\)的树,满足\(l\)的每一个元素唯一对应为一条边的长度,并使整棵树的直径长度恰好为\(d\)。Solution不妨令\(l_1\lel_2\le\cdots\lel_......
  • CodeForces 1906K Deck-Building Game
    洛谷传送门CF传送门UNR#2黎明前的巧克力。枚举两个人选的卡的并集\(S\),那么当\(\bigoplus\limits_{i\inS}a_i=0\)时\(S\)有贡献\(2^{|S|}\)。考虑将\(2^{|S|}\)分摊到每个元素上,也就是每个元素有\(2\)的贡献,然后把这些贡献乘起来。所以题目其实是想让我们算......
  • Codeforces1917E - Construct Matrix
    Codeforces1917E-ConstructMatrix首先考虑因为\(n\)为偶数,所以\(k\)为奇数时不可能满足条件。其次,如果\(4|k\),那么实际上在矩阵中一直放\(2\times2\)的全为\(1\)的矩阵就可以了。随后,如果\(k\equiv2\mod4\),那么可以证明如果\(k\ne2\landk\nen^2-2\),......
  • Codeforces Round 917 (Div. 2)
    基本情况A题秒了,B题卡了一年。B.EraseFirstorSecondLetterProblem-B-Codeforces卡题分析两方面原因没有变通,一开始的思路是公式算出总字串数再想办法找重复的减掉,但搞了一个小时都不可行,应该早点换成正着来找的思路。没有更深入的分析样例。最后虽然出来了,......
  • codeforces刷题(1100):1907C_div3
    C、RemovalofUnattractivePairs跳转原题点击此:该题地址1、题目大意  给定一个字符串,可以删除相邻的两个不相等的字符。问你删除后能得到最小的字符串长度为多少。2、题目解析  因为只要两个不相等的字符相邻就能消除,所以只需要找到数量最多的字符,只要它的数量比其它字......
  • CodeForces 1909E Multiple Lamps
    洛谷传送门CF传送门感觉这个题比较难蚌。发现按\(1\simn\)最后可以把\(1\simn\)中的所有平方数点亮。所以\(n\ge20\)就直接输出\(1\simn\)。考虑\(n\le19\)。猜测合法的方案(即按完后亮灯数\(\le\left\lfloor\frac{n}{5}\right\rfloor\)的方案,不考虑\((......
  • CodeForces 1909D Split Plus K
    洛谷传送门CF传送门设最后每个数都相等时为\(t\)。那么一次操作变成了合并两个数\(x,y\),再增加\(x+y-k\)。于是每个\(a_i\)可以被表示成\(b_it-(b_i-1)k\)的形式,化简得\(a_i-k=b_i(t-k)\)。因为\(t-k\)对于每个\(i\)都相同,又因为我们的目标是......
  • CodeForces 1909F2 Small Permutation Problem (Hard Version)
    洛谷传送门CF传送门感觉这个题还是挺不错的。考虑F1。考察\(a_i\)差分后的意义,发现\(a_i-a_{i-1}\)就是\((\sum\limits_{j=1}^{i-1}[p_j=i])+p_i\lei\)。考虑将其转化为棋盘问题。在\((i,p_i)\)放一个车,那么\(a_i-a_{i-1}\)就是\((1,i)\sim......