首页 > 其他分享 >「CF1854D」Michael and Hotel 题解

「CF1854D」Michael and Hotel 题解

时间:2025-01-22 10:59:50浏览次数:1  
标签:const log int 题解 Hotel Michael using circle 节点

逆天交互题、、、我只能说阈值分治赛高!!!

Description

有一个有 \(n\) 个点的内向基环树森林,zlsim 位于 \(1\) 号节点,请你通过以下操作求出哪些节点(包括 )可以通过从这两点开始沿边行走若干步汇至一点。

  • 给出两个参数 \(u,k\) 和点集 \(S\),询问是否能够通过从 \(u\) 出发走 \(k\) 步达到任意 \(S\) 中的节点。
    你最多可以询问 \(2000\) 次。

Solution

十分严谨的推导过程:

  • 一个节点走足够多步一定可以走到环;
  • 只要走到的环是 \(1\) 号节点所属,就满足条件。
    据此,问题转化为了求 \(1\) 号节点最后到达的环有哪些节点(不关注次序)。
    我们再理一下我们可以使用的操作组(不一定全):
  1. 使用 \(\log n\) 次询问找到 \(u\) 出发走 \(k\) 步到达的节点;
  2. 使用 \(n\) 次查询找到环上连续 \(k\) 个点的前面 \(k\) 个点。
    容易发现,操作组 \(2\) 是一个倍增的形式,但倍增的前几次操作损耗太大,可以使用操作 \(1\) 来解决,形成一个阈值分治的形式。由于最后我们还要询问 \(n\) 次,令进行操作组 \(1\) \(k\) 次,有询问次数 \(k\log n+n\log \frac{n}{k}+n\)。易知当 \(k\log k=n\) 时,原式存在最小值 \(n+2k\log n\)。当 \(n=500,k=80\) 时,大概为 \(1935\)。可以通过此题。

Code

#include <bits/stdc++.h>
using namespace std;

using ci = const int;

using u32 = uint32_t;
using i64 =  int64_t;
using u64 = uint64_t;

template<class T> inline void Max(T &x, const T &y) { if (x < y) x = y; }
template<class T> inline void Min(T &x, const T &y) { if (y < x) x = y; }

const int N = 505;
const int K = 80;

int n, circle_begin;
set<int> circle;

int get_val() {
	bool val;
	cin >> val;
	return val;
}

bool ask1(int u, int k, int l, int r) {
	cout << "? " << u << " " << k << " " << r - l + 1 << " ";
	for (int i = l; i <= r; ++i) cout << i << " ";
	cout << endl;
	return get_val();
}

bool ask2(int u, int k) {
	cout << "? " << u << " " << k << " " << circle.size() << " ";
	for (int i : circle) cout << i << " ";
	cout << endl;
	return get_val();
}

int u_k(int u, int k) {
	int l = 1, r = n, mid;
	while (l < r) {
		mid = (l + r) >> 1;
		if (ask1(u, k, l, mid)) r = mid;
		else l = mid + 1;
	}
	return l;
}

void output() {
	vector<int> ans;
	for (int i = 1; i <= n; ++i) {
		if (circle.count(i) or ask2(i, n)) ans.push_back(i);
	}
	cout << "! " << ans.size() << " ";
	for (int i : ans) cout << i << " ";
	cout << endl;
	exit(0);
}

int main() {
	ios_base::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);

	cin >> n;
	int p = circle_begin = u_k(1, n);

	circle.insert(p);

	for (int i = 2; i <= K; ++i) {
		p = u_k(p, 1);
		if (p == circle_begin) output();
		circle.insert(p);
	}

	int now_k = K;
	while (1) {
		vector<int> ls;
		for (int i = 1; i <= n; ++i) {
			if (!circle.count(i) and ask2(i, now_k)) ls.push_back(i);
		}
		for (int i : ls) circle.insert(i);
		if (ls.size() < now_k) output();
		now_k <<= 1;
	}

	return 0;
}

标签:const,log,int,题解,Hotel,Michael,using,circle,节点
From: https://www.cnblogs.com/cqbzljh/p/18685290

相关文章

  • P9678 题解
    题意给定一棵\(n\)个点的树\(T\),边有边权。现在有\(q\)组询问,每组询问给出\(l,r\),求出:\[\min_{l\lei<j\ler}\operatorname{dist}(i,j)\]\(n\le2\times10^5\),\(q\le10^6\),\(1\lew\le10^9\)。由于与路径长度有关,所以考虑点分治或者LCA。由于笔......
  • ZJOI2010 基站选址 题解
    ZJOI2010基站选址题解题目链接dp+线段树优化。暴力dp状态设计:自然想到设\(f(i,j)\)表示只考虑前\(i\)个村庄,在前\(i\)个村庄中建\(j\)个基站,并且在第\(i\)个存在建立基站时,最小的费用。转移:转移时,枚举上一个建基站的村庄\(p\)(这同时告诉我们,\(j=1\)......
  • P1048 [NOIP2005 普及组] 采药 题解
    原题链接题目大意:采药,每种药只有一株,每株有它的价值和采它所需的时间,现时间有限,请你输出在有限时间内能获得的价值最大是多少。分析:1.这是一个典型的01背包问题(DP)01背包问题的典型特征:有一个限定容量的背包(对应本题中的时间),有物品(每种只有一个)(对应本题中的药株),物品有......
  • 洛谷P1002 [NOIP2002 普及组] 过河卒 题解
    原题链接题目大意:棋盘上A点有一个过河卒,需要走到目标B点。卒行走的规则:向下或向右。同时在棋盘上C点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点。棋盘用坐标表示,AA点(0,0)、BB点(n,m),同样马的位置坐标是需要给出的。现在要求你计算出......
  • 2025牛客寒假算法基础集训营1 ptlks的题解
    A.茕茕孑立之影题意:给定序列,找出一个数x,满足x和数组中任意一个元素都互不为倍数关系思路x范围为1e18以内,序列元素范围为1e9以内,选大于1e9的质数即可,特判序列中有1的情况。代码点击查看代码voidsolve(){ intn; cin>>n; intf=1; for(inti=1;i<=n;i++){ cin>>a[......
  • 题解:洛谷 P4879 ycz的妹子
    题目https://www.luogu.com.cn/problem/P4879感觉还比较简单的线段树。首先我们先建立一棵线段树(范围:)。voidbuild(intk,intl,intr){ tr[k]={l,r}; if(l==r){ Tree[k]=a[l],c[k]=(l<=n); return; } intmid=(l+r)>>1ll; build(k<<1ll,l,mid); build((k<<1ll)|1l......
  • 题解:洛谷 P1351 [NOIP2014 提高组] 联合权值
    题目https://www.luogu.com.cn/problem/P1351我们可以发现,若点对  的距离为 ,则它们一定会经过一个中转点,因此我们考虑枚举中转点 ,然后枚举与  有直接边连接的两个点,按照题意统计答案即可。#include<bits/stdc++.h>usingnamespacestd;#pragmaG++optimisze(3,"Ofas......
  • 【题解】Luogu P4340 [SHOI2016] 随机序列
    简单手摸后发现,答案就是这么一个式子:\[(3^{n-1}-3^{n-2})a_1+(3^{n-2}-3^{n-3})a_1a_2+\dots+(3^1-3^0)a_1a_2\dotsa_{n-1}+a_1a_2\dotsa_n\]啊当然证明也是好证的,对于\(a_1\)这一项,它后面放+或-都会对系数加一,而放*不会影响系数,因此系数就是总数的三分之二。其它前缀......
  • 题解:P3823 [NOI2017] 蚯蚓排队
    题目链接https://www.luogu.com.cn/problem/P3823分析先解决队伍的合并与分离问题。使用链表结构,分别维护每只蚯蚓的前驱和后继即可。然后考虑如何统计答案。可以对每只蚯蚓的“向后\(k\)数字串”使用字符串哈希的方式获得哈希值,再用一个哈希表存储每个哈希值出现的次数。对......
  • 2024 (ICPC) Jiangxi Provincial Contest I 题 Neuvillette Circling题解
    简单思路一个圆套中了几个点,如果不断缩小这个圆,那么最终的结果有两种有两个点卡住了这个圆,且这两点一定是直径有三个或者三个以上的点卡住了这个圆,圆心在这三个点围成的三角形的外接圆圆心。因此我们枚举两点作为直径,或者枚举三个点作为圆的内接三角形,求这个三角形的外接圆......