比赛链接:

https://codeforces.com/contest/1698

C. 3SUM Closure

题意:

给定一个序列 \(a\),判断对于任意一个 \(1 <= i < j < k <= n\),是否存在一个 \(1 <= l <= n\),使得 \(a[i] + a[j] + a[k] = a[l]\)

思路:

首先如果有三个正数及以上的正数,那么选择其中最大的三个,它们的和肯定不在序列中,同理得到负数也不会超过三个。
对于 0 而言,容易知道,最多只会有两个 0 对结果产生影响(两个 0 或一个 0,与正数或者负数组合一下)。
这样算下来最多只有 6 个数对结果产生影响,暴力枚举一下即可。

代码:

#include <bits/stdc++.h>
using namespace std;
#define LL long long
void solve(){
	LL n;
	cin >> n;
	vector <LL> a(n), b;
	LL pos = 0, neg = 0, cnt = 0;
	for (int i = 0; i < n; i ++ ){
		cin >> a[i];
		if (a[i] > 0){
			pos ++ ;
			b.push_back(a[i]);
		}
		else if (a[i] < 0){
			neg ++ ;
			b.push_back(a[i]);
		}
		else{
			cnt ++ ;
		}
	}
	if (pos >= 3 || neg >= 3){
		cout << "NO\n";
	}
	else{
		cnt = min(cnt, 2LL);
		for (int i = 0; i < cnt; i ++ ){
			b.push_back(0);
		}
		LL m = b.size();
		map <LL, LL> mp;
		for (int i = 0; i < m; i ++ ){
			mp[b[i]] = 1;
		}
		for (int i = 0; i < m; i ++ ){
			for (int j = 0; j < m; j ++ ){
				for (int k = 0; k < m; k ++ ){
					if (i == j || j == k || i == k) continue;
					LL t = b[i] + b[j] + b[k];
					if (mp[t] == 0){
						cout << "NO\n";
						return;
					}
				}
			}
		}
		cout << "YES\n";
	}
}
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	LL T;
	cin >> T;
	while (T -- )
		solve();
	return 0;
}

D. Fixed Point Guessing

题意:

给定一个排列,现在对其中的 \(n - 1\) 个数进行两两交换(\(n\) 为奇数),即只有一个数的位置是不变的。
可以最多进行 15 次询问去找出这个数,每次询问输出 \(? l r\),返回序列打乱后,\(l\)\(r\) 的元素进行升序排序之后的子序列。

思路:

通过数据范围可以推测出二分。
对于 \(l\)\(r\) 这个排序好的序列的元素,如果它在区间范围内,说明它是内部的交换,否则它是外部的交换。
如果内部的交换次数为奇数,说明有一个元素的位置没有发生变换(其它内部元素两两交换的)。

代码:

#include <bits/stdc++.h>
using namespace std;
#define LL long long
bool ask(LL a, LL b){
	cout << "? " << a << " " << b << "\n";
	vector <LL> t(b - a + 1);
	for (int i = 0; i < b - a + 1; i ++ ){
		cin >> t[i];
	}
	LL cnt = 0;
	for (int i = 0; i < b - a + 1; i ++ ){
		if (a <= t[i] && t[i] <= b){
			cnt ++ ;
		}
	}
	return cnt % 2;
}
void solve(){
	LL n;
	cin >> n;
	LL l = 1, r = n;
	while (l < r){
		LL mid = (l + r) >> 1;
		if (ask(l, mid)){
			r = mid;
		}
		else{
			l = mid + 1;
		}
	}
	cout << "! " << l << "\n";
}
int main(){
	LL T;
	cin >> T;
	while (T -- )
		solve();
	return 0;
}
posted on 2022-07-04 20:46  Hamine  阅读(49)  评论(0编辑  收藏  举报