首页 > 其他分享 >「解题报告」[ABC267F] Exactly K Steps

「解题报告」[ABC267F] Exactly K Steps

时间:2023-10-16 14:46:13浏览次数:44  
标签:tmp sz ABC267F int Exactly dep Steps return mx

「解题报告」[ABC267F] Exactly K Steps

大家好,我是个毒瘤,我非常喜欢没脑子做法,于是我就用点分治过了这个题 .

离线在每个点存下与其相关的询问 . 考虑如何计算跨重心的答案 .

记录下每个点在当前重心下的深度,同时开一个桶 \(t_{k, 0/1}\) 存下当前深度为 \(k\) 的,来自重心的不同子树的两个点 .

把记录深度的搜索过程中遇到的询问拿出来,在记录完桶之后处理 . 具体的,对于一个询问 \((u, k)\),查找桶 \(t_{k - dep_u,0/1}\) 内是否有与 \(u\) 不在同一棵子树的点 . 需要特殊处理一下 \(k-dep_u = 0\) 的询问 .

具体实现细节可以看代码 .

询问虽然不是一次性全能处理完的,但是由于点分治最多递归 \(\log n\) 层,每个询问也最多只会被取出 \(\log n\) 次,时间复杂度是 \(O((n+q)\log n)\) .

Code:

const int N = 2e5 + 10, P = 998244353;
namespace SOLVE {
	int n, q, ans[N];
	std::vector <int> tu[N];
	std::vector <pii> qu[N];
	inline int rnt () {
		int x = 0, w = 1; char c = getchar ();
		while (!isdigit (c)) { if (c == '-') w = -1; c = getchar (); }
		while (isdigit (c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar ();
		return x * w;
	}
	int root, sz[N], tmp[N][2][2], mx[N];
	bool vis[N];
	class T {
	public:
		int u, d, r;
		T () = default;
		T (int _u, int _d, int _r): u(_u), d(_d), r(_r) {}
	};
	std::queue <T> qa;
	void DFS_Find (int u, int fa, int dep, int r) {
		if (!qu[u].empty ()) qa.push (T (u, dep, r));
		if (!tmp[dep][0][0]) tmp[dep][0][0] = u, tmp[dep][0][1] = r;
		else if (!tmp[dep][1][0] && tmp[dep][0][1] != r) tmp[dep][1][0] = u, tmp[dep][1][1] = r;
		far (v, tu[u]) {
			if (vis[v] || v == fa) continue;
			DFS_Find (v, u, dep + 1, r);
		}
		return;
	}
	int DFS_MaxDep (int u, int fa, int dep) {
		int mx = dep;
		far (v, tu[u]) if (!vis[v] && v != fa)
			mx = std::max (mx, DFS_MaxDep (v, u, dep + 1));
		return mx;
	}
	inline void Calc (int u) {
		far (v, tu[u]) {
			if (vis[v]) continue;
			DFS_Find (v, u, 1, v);
		}
		if (!qu[u].empty ()) qa.push (T (u, 0, u));
		while (!qa.empty ()) {
			T f = qa.front (); qa.pop ();
			far (p, qu[f.u]) {
				if (ans[p.second]) continue;
				int d = p.first - f.d;
				if (d < 0) continue;
				else if (d == 0) ans[p.second] = u;
				else {
					if (f.r == tmp[d][0][1]) ans[p.second] = tmp[d][1][0];
					else ans[p.second] = tmp[d][0][0];
				}
			}
		}
		int mxd = DFS_MaxDep (u, 0, 0);
		_for (i, 0, mxd) tmp[i][0][0] = tmp[i][0][1] = tmp[i][1][0] = tmp[i][1][1] = 0;
		return;
	}
	void GetRoot (int u, int fa) {
		mx[u] = 0, sz[u] = 1;
		far (v, tu[u]) {
			if (vis[v] || v == fa) continue;
			GetRoot (v, u), sz[u] += sz[v];
			mx[u] = std::max (mx[u], sz[v]);
		}
		mx[u] = std::max (mx[u], sz[0] - sz[u]);
		if (mx[root] > mx[u]) root = u;
		return;
	}
	void GetSize (int u, int fa) {
		sz[u] = 1;
		far (v, tu[u]) {
			if (vis[v] || v == fa) continue;
			GetSize (v, u), sz[u] += sz[v];
		}
		return;
	}
	void Divide (int u) {
		Calc (u), vis[u] = true;
		far (v, tu[u]) {
			if (vis[v]) continue;
			sz[0] = sz[v], mx[root = 0] = N;
			GetRoot (v, u), GetSize (root, u);
			Divide (root);
		}
		return;
	}
	inline void In () {
		n = rnt ();
		_for (i, 1, n - 1) {
			int u = rnt (), v = rnt ();
			tu[u].emplace_back (v);
			tu[v].emplace_back (u);
		}
		q = rnt ();
		_for (i, 1, q) {
			int u = rnt (), d = rnt ();
			qu[u].emplace_back (d, i);
		}
		return;
	}
	inline void Solve () {
		root = 0, sz[0] = n, mx[0] = N;
		GetRoot (1, 0), GetSize (root, 0);
		Divide (root);
		return;
	}
	inline void Out () {
		_for (i, 1, q) printf ("%d\n", ans[i] ? ans[i] : -1);
		return;
	}
}

标签:tmp,sz,ABC267F,int,Exactly,dep,Steps,return,mx
From: https://www.cnblogs.com/K8He/p/solution-at-abc267-f.html

相关文章

  • Exactly Once 语义在Flink中的实现
    数据流和动态表SQL和流处理的区别流式数据是一种实时生成的数据,而在一般的数据表中存储的数据肯定是有限的,这就会产生矛盾,由此就需要一种新表来存储流式数据,动态表就产生了。动态表动态表与表示批处理数据的静态表不同,动态表是随时间变化的。可以像查询静态批处理表一样查询它......
  • Test class should have exactly one public zero-argument constructor(测试类应该只
    在练习重写equals方法时写测试方法遇到这个问题先放报错代码:publicclassOrder{intorderId;StringorderName;publicintgetOrderId(){returnorderId;}publicvoidsetOrderId(intorderId){this.orderId=orderId;}......
  • 【Vue】关于 The template root requires exactly one element 报错的解决方案
     在<template>内添加<div>总括起来: ......
  • 逐帧动画steps函数用法
    animation-timing-function:steps(number,[end|start])steps(number,[end|start])是将动画分为number段,共有number+1帧画面。start就是抛弃第一帧画面执行动画,end就是抛弃最后一帧画面执行动画。steps的number参数并不是将整个动画过程切割成number段,而是对于某个c......
  • Pytest allure中steps中添加日志
    是否在使用allure时,为了更好的定位问题,会把日志添加上去。类似如下的情行:#!/usr/bin/envpython#-*-coding:utf-8-*-#@Time:2023/7/189:12#@Author:huzq#@File:test_allure.pyimportloggingimportallureimportpytestLOG=logging.getLogger(......
  • Vue2或Vue3中实现页面锚点滚动(结合AntDesign a-steps
    核心代码 onStepChange(current){ this.current=current; document.querySelector(`[id='${current}']`).scrollIntoView({ behavior:"smooth",//定义过渡动画instant立刻跳过去smooth平滑过渡过去 block:"start",//定义垂直滚动方向的对齐start顶部(......
  • [CF1139D]Steps to One
    Preface不会dp,所以反演(感谢@judgelight)。Solution考虑期望式子:\[\begin{aligned}E(len)&=\sum_iP(len=i)\timesi\\&=\sum_iP(len=i)\sum_{j=1}^i1\\&=\sum_i\sum_{j=1}^iP(len=i)\\&=\sum_j\sum_{i\gej}P(len=i)\\&=\sum_jP(len\ge......
  • [Vue warn]: Error compiling template: Component template should contain exactly
    报错信息:[Vuewarn]:Errorcompilingtemplate:Componenttemplateshouldcontainexactlyonerootelement.Ifyouareusingv-ifonmultipleelements,usev-else-iftochaintheminstead.2|3|4||......
  • [LeetCode] 1347. Minimum Number of Steps to Make Two Strings Anagram 制造字母异
    Youaregiventwostringsofthesamelength s and t.Inonestepyoucanchoose anycharacter of t andreplaceitwith anothercharacter.Return theminimumnumberofsteps tomake t ananagramof s.An Anagram ofastringisastringthatco......
  • AtCoder Beginner Contest 258 Ex Odd Steps
    洛谷传送门AtCoder传送门不错的矩阵快速幂优化dp练习题。考虑一个朴素dp,\(f_i\)为组成和为\(i\)且用到的数都是奇数的方案数。有转移:\[f_i=\begin{cases}\sum\limits_{j=0}^{i-1}[i\bmod2\nej\bmod2]f_j&i\notinA\\0&i\inA\end{cases}\]考虑前......