CF1702F 题解

洛谷传送门 & CF 传送门

思路

初看这一题,这题难搞的地方就在于有两种操作,所以我们可以考虑先做完一种操作,再去单独地做第二种。我们可以发现,先把 xx 替换成 2x2x,再把 xx 替换为 x2\lfloor\frac x2\rfloor 时,操作前和操作后的 xx 值不变,因为这时的向下取整不起作用;但先把 xx 替换为 x2\lfloor\frac x2\rfloor,再把 xx 替换成 2x2x 后,操作前后的 xx 就不一定相等了。所以,我们就可以考虑先做第一种操作,再做第二种操作。

第一种操作并不是单纯地把 bib_i 不断乘 22,而是把所有 aia_ibib_i 都不断除以 22,直到所有数变为奇数为止。这时候,我们的第二种操作就可以开始了。

第二种操作也不能普通操作,否则太慢了。我们需要操作的是所有 bib_i 中最大的一个 yy。我们需要拿 aia_i 中最大的数 xx 与它作比较,分类考虑:

  1. x>yx>y 时,由于这时 yy 是单调不减的了,所以直接无解;
  2. x<yx<y 时,我们直接把 yy 进行一次操作(除以 22)即可;
  3. x=yx=y 时,这时候我们直接把 xxyy 都删掉即可。

这里每次要求 xxyy,我们可以使用 STL 的优先队列 O(logn)O(\log n) 快速解决。

代码

# include <bits/stdc++.h>
using namespace std;
int t, n, m, x;
priority_queue <int> q1, q2;
void clear (priority_queue <int>& q) {
	while (! q.empty ())
		q.pop ();
	return ;
}
int main () {
	ios::sync_with_stdio (0);
	cin.tie (0);
	cout.tie (0);
	cin >> t;
	while (t --) {
		cin >> n;
		clear (q1), clear (q2); //手动清空优先队列
		for (int i = 0; i < n; ++ i) {
			cin >> x;
			while (! (x & 1)) //不断除以 2
				x >>= 1;
			q1.push (x);
		}
		for (int i = 0; i < n; ++ i) {
			cin >> x;
			while (! (x & 1))
				x >>= 1;
			q2.push (x);
		}
		while (! q1.empty ())
			if (q1.top () < q2.top ())
				q2.push (q2.top () >> 1), q2.pop (); //记得 pop
			else if (q1.top () > q2.top ()) {
				cout << "NO\n";
				goto END; //goto 是个好东西,可以直接跳转到 END 继续执行
			} else
				q1.pop (), q2.pop ();
		cout << "YES\n"; //有解
END: ;
	}
	return 0;
}
posted @   sz_jinzikai  阅读(5)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示