首页 > 其他分享 >题解 CF1773H【Hot and Cold】

题解 CF1773H【Hot and Cold】

时间:2023-01-25 19:47:08浏览次数:51  
标签:return string success xm 题解 Hot CF1773H ask ym

赛时跟队友一起摆烂了,于是没做出来,回来补题。

如果询问到了答案,可以直接判断并退出,因此下文的询问过程并没有考虑这一点。

显然“\((1,1)\) 比 \((0,0)\) 离所求位置更近”对于几乎所有点成立,因此我们可以依次询问 \((0,0),(1,1),(0,0)\),忽略第一次的回答,则后两次回答分别对应 CloserFurther,记为 \(c\) 和 \(f\)。我们说“几乎所有点”,因为存在两个反例 \((0,1),(1,0)\)。容易发现反例情况 \(c=f\)(因为其实都对应 At the same distance),此时把两种情况都问一下即可得到答案。

通过以上过程,我们排除了平凡情况,并确定了 \(c\) 和 \(f\)。考虑二分,设所求位置在 \((x_l,y_l)\sim(x_r,y_r)\) 的子矩形中,求出中点 \((x_m,y_m)\),依次询问 \((x_m,y_m),(x_m+1,y_m),(x_m+1,y_m+1)\),忽略第一次的回答,则后两次的回答分别可以使 \(x\) 和 \(y\) 的范围减半。于是我们可以在 \(3\lceil\log_210^6\rceil+4=64\) 次询问内确定所求点。

有两点需要注意:

  • 可以发现询问次数上限卡得很紧,要精细实现不要写丑多询问。
  • 需要特判当 \(x_m\) 或 \(y_m\) 恰好等于 \(10^6\) 的情况,此时会涉及到坐标 \(10^6+1\) 从而导致不合法询问。
// Problem: CF1773H Hot and Cold
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/CF1773H
// Memory Limit: 1000 MB
// Time Limit: 3000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

//By: OIer rui_er
#include <bits/stdc++.h>
#define rep(x,y,z) for(int x=(y);x<=(z);x++)
#define per(x,y,z) for(int x=(y);x>=(z);x--)
#define debug(format...) fprintf(stderr, format)
#define fileIO(s) do{freopen(s".in","r",stdin);freopen(s".out","w",stdout);}while(false)
using namespace std;
typedef long long ll;

string c, f;
template<typename T> void chkmin(T& x, T y) {if(x > y) x = y;}
template<typename T> void chkmax(T& x, T y) {if(x < y) x = y;}
string ask(int x, int y) {
	printf("%d %d\n", x, y);
	fflush(stdout);
	string res;
	getline(cin, res);
	return res;
}
bool success(string s) {
	return s.find('!') != string::npos;
}

int main() {
	if(success(ask(0, 0))) return 0;
	if(success(c = ask(1, 1))) return 0;
	if(success(f = ask(0, 0))) return 0;
	if(c == f) return assert(success(ask(0, 1)) || success(ask(1, 0))),0;
	int xl = 0, xr = 1000001, yl = 0, yr = 1000001;
	while(xl < xr || yl < yr) {
		int xm = (xl + xr) >> 1, ym = (yl + yr) >> 1;
		string res1, res2;
		if(success(ask(xm, ym))) return 0;
		if(xm == 1000000 && ym == 1000000) res1 = res2 = f;
		else if(xm == 1000000) {
			res1 = f;
			if(success(res2 = ask(xm, ym+1))) return 0;
		}
		else if(ym == 1000000) {
			if(success(res1 = ask(xm+1, ym))) return 0;
			res2 = f;
		}
		else {
			if(success(res1 = ask(xm+1, ym))) return 0;
			if(success(res2 = ask(xm+1, ym+1))) return 0;
		}
		if(res1 == c) xl = xm + 1;
		else xr = xm;
		if(res2 == c) yl = ym + 1;
		else yr = ym;
	}
	assert(success(ask(xl, yl)));
	return 0;
}

标签:return,string,success,xm,题解,Hot,CF1773H,ask,ym
From: https://www.cnblogs.com/ruierqwq/p/CF-1773H.html

相关文章

  • Xbox One 手柄在 Steam 上截图 - Xbox One Controller Gamepad Screenshot on Steam
    Steam手柄如何截图/XboxOne手柄怎么截图/Xbox旧手柄怎么截图?答案如下:via:Howtotakescreenshotsusingxboxonecontroller?::HelpandTipsGuide+R......
  • 关于gnome-control-center的问题解决
    突然发现电脑桌面的设置无法打开,点击后一直转圈。在网上研究了一圈,发现可能是gnome出了问题,输入指令gnome-control-center,结果报了如下错误:gnome-control-center:......
  • Windows: Screenshot
     全屏:到clipboardfn+printscreen 保存到C:\Users\Memento\Pictures\Screenshotsfn+win+printscreen f SnippingToolwin+shift......
  • 洛谷 P1478 陶陶摘苹果(升级版) 题解
    这道题只要会自定义cmp恰当地进行排序,其他部分没有什么大问题。上代码:1#include<bits/stdc++.h>2usingnamespacestd;3intn,s,h1,h2,cnt;4structapple{......
  • CF Educational Round 142 (Rated for div2) 题解
    A注意到除了血量为\(1\)的怪物,其余的怪物直接斩杀是更合理的。所以只要统计血量为\(1\)的怪物的个数即可。#include<cstdio>voidsolve(){ intn;scanf("%d",......
  • 洛谷 P1094纪念品分组 题解
    一道典型的贪心算法题。题目内容不多说了,大致说一下代码的思路:给定的所有纪念品中可以先用sort排一下顺序,然后从价格最高和最低的开始向中间靠拢(可以看做是指针),这样保证......
  • 洛谷 P2440木材加工 题解
    这是一道二分答案算法题,洛谷标签中的贪心等完全用不到。这道题的数据范围较大,所以保险起见,整型的数据我们都开成longlong题意很好理解,这里就不做过多的分析了,直接看代码......
  • 洛谷P1259 黑白棋子的移动 题解
    本蒟蒻这题用的打表做法,其实也可以理解为是一种递推。先来观察一下样例:当n为7时,输出共有14行,易得输出行数为2n。ooooooo*******--oooooo--******o*oooooo******--o......
  • LeetCode-670. 最大交换-题解分析
    题目来源670.最大交换题目详情给定一个非负整数,你至多可以交换一次数字中的任意两位。返回你能得到的最大值。示例1:输入:2736输出:7236解释:交换数字2和数字......
  • 题解 ARC154D【A + B > C ?】
    显然\(1+1>x\)对任意大于\(1\)的正整数\(x\)都不成立。利用这一点,我们可以在\(n-1\)次询问内问出\(1\)的位置。具体地,首先假设\(p_1\)为\(1\),记我们假设的为......