比赛链接:

https://codeforces.com/contest/1697

C. awoo's Favorite Problem

题意:

有一个字符串 \(s\),每次可以选择一个字串 "ab" 将其改为 "ba" 或者选择 "bc" 将其改为 "cb"。再给定一个字符串 \(t\),问是否可以通过若干次操作让 \(s\) 变成 \(t\)

思路:

首先看两个字符串中 'a','b','c' 三个字符的数量是否相等,然后看两个操作的本质。
两个操作分别是让 \(a\) 向后移动,让 \(c\) 向前移动,可以发现 \(a\)\(c\) 的相对位置是不会发生变化的,所以先将 \(b\) 从字符串中去掉,判断剩下的字符串是否相等。
接着看它们的相对位置是不是正确即可。

代码:

#include <bits/stdc++.h>
using namespace std;
#define LL long long
void solve(){
	LL n;
	cin >> n;
	string s, t;
	cin >> s >> t;
	for (char c = 'a'; c <= 'c'; c ++ ){
		if (count(s.begin(), s.end(), c) != count(t.begin(), t.end(), c)){
			cout << "NO\n";
			return;
		}
	}
	vector <LL> ids, idt;
	for (int i = 0; i < n; i ++ ){
		if (s[i] != 'b'){
			ids.push_back(i);
		}
		if (t[i] != 'b'){
			idt.push_back(i);
		}
	}
	for (int i = 0; i < (int)ids.size(); i ++ ){
		if (s[ids[i]] != t[idt[i]]){
			cout << "NO\n";
			return;
		}
	}
	if (ids.size() != idt.size()){
		cout << "NO\n";
		return;
	}
	for (int i = 0; i < (int)ids.size(); i ++ ){
		if (s[ids[i]] == 'a'){
			if (ids[i] > idt[i]){
				cout << "NO\n";
				return;
			}
		}
		else if (s[ids[i]] == 'c'){
			if (ids[i] < idt[i]){
				cout << "NO\n";
				return;
			}
		}
	}
	cout << "YES\n";
}
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	LL T = 1;
	cin >> T;
	while(T -- ){
		solve();
	}
	return 0;
}

D. Guess The String

题意:

有一个长为 \(n\) 的字符串,通过查询去推出这个字符串是什么。
有两种查询方式:
第一种查询,输出 "? 1 p",会返回 \(p\) 这个位置的字符。该查询不能超过 26 次。
第二种查询,输出 "? 2 l r",会返回 \(l\)\(r\) 区间中的字符的种类。该查询不能超过 6000 次。

思路:

首先第一种查询肯定是为了确定每一种字母的位置。可以通过 1000 次的第二种查询 + 不超过 26 次的第一种查询去确定每个字母第一次出现的位置。
只要每次查询 "? 2 1 i",询问 \([1, i]\) 区间中的字母种类,如果和 \([1, i - 1]\) 不一样的话,说明没出现过,那就通过第一种查询查一下。这里最多会用 1000 次第二种查询。
如果一样的话,说明该字母在之前出现过,用 \(id\) 数组去记录第 \(i\) 位之前每种字母最后出现的位置,那每次查询 "? 2 id i" 的时候,就可以知道第 \(i\) 个字母是之前的那一个字母了。这里最多用了 1000 * \(log_2^26\) 次第二种查询,不超过 5000。所以总的不超过 6000 次。

代码:

#include <bits/stdc++.h>
using namespace std;
#define LL long long
char ask1(int x){
	cout << "? 1 " << x << "\n";
	char c;
	cin >> c;
	return c;
}
int ask2(int L, int R){
	cout << "? 2 " << L << " " << R << "\n";
	int t;
	cin >> t;
	return t;
}
int main(){
	LL n;
	cin >> n;
	LL sum = 0;
	vector <LL> id;
	vector <char> ans(n + 1);
	for (int i = 1; i <= n; i ++ ){
		int t = ask2(1, i);
		if (t > sum){
			char c = ask1(i);
			ans[i] = c;
			id.push_back(i);
			sum ++ ;
		}
		else{
			LL L = 0, R = id.size() - 1;
			while(L < R){
				LL mid = (L + R + 1) >> 1;
				int t = ask2(id[mid], i);
				if (t != (int)id.size() - mid + 1) L = mid;
				else R = mid - 1;
			}
			ans[i] = ans[id[L]];
			id[L] = i;
			sort(id.begin(), id.end());
		}
	}
	cout << "! ";
	for (int i = 1; i <= n; i ++ )
		cout << ans[i];
	cout << "\n";
	return 0;
}
posted on 2022-07-17 11:23  Hamine  阅读(36)  评论(0编辑  收藏  举报