Codeforces Global Round 17 A-C (思维题,模拟,二分)

A:思维题,观察后很容易发现
最难猜的情况是所有点都被电脑选定了(也就是不会提供额外信息)
所以以下的所有分析都是基于所有点都是可疑点
n==1&&m==1,显然不需要探测就能知道目标点在哪
n==1||m==1我们只需要探测这一条线上的一段,即可得知目标点
其他情况:均为2,只需要将两个点放在矩形的左上角与右下角,此时两圆相接确定一个点

#pragma GCC optimize(3,"Ofast","inline")
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
int n, m;
 
 
void solve() {
    
    
	cin >> n >> m;
	if (n > m)
		swap(n, m);
	if (n == 1 && m == 1) {
    
    
		cout << "0" << endl;
		return;
	}
	if (n == 1 ) {
    
    
		cout << "1" << endl;
		return;
	} else {
    
    
		cout << "2" << endl;
		return;
	}
}
 
signed main() {
    
    
	ios::sync_with_stdio(false);
	int t;
	cin >> t;
	while (t--)
		solve();
 
}
 

B:假设要删数字X,易知,删除部分X对答案的影响等价于删除全部X对答案的影响。(如果只删除部分,如果剩下的字符串是回文的,剩下的X也会互相配对----等价于没有)
所以只需要从两端往中间搜,找到第一个冲突点A,B.分裂出剔除掉A或B两种情况,只要其中一个情况合法,即可行

#include <bits/stdc++.h>
#define long long
#define endl '\n'
using namespace std;
int n, m;
const int N = 2e5 + 10;
int a[N];
vector<int>g1, g2;
int tag1 = 0, tag2 = 0;
 
bool check1() {
    
    
	for (int i = 1; i <= n; i++) {
    
    
		if (a[i] != a[n - i + 1]) {
    
    
			tag1 = a[i];
			tag2 = a[n - i + 1];
			return false;
		}
	}
	return true;
}
 
bool check2() {
    
    
	int l = g1.size() - 1;
	int l2 = g2.size() - 1;
	int ok = 0;
	for (int i = 1; i <= l; i++) {
    
    
		if (g1[i] != g1[l + 1 - i]) {
    
    
			ok = 1;
			break;
		}
	}
	if (!ok) {
    
    
		return true;
	}
	ok = 0;
	for (int i = 1; i <= l2; i++) {
    
    
		if (g2[i] != g2[l2 + 1 - i ]) {
    
    
			ok = 1;
			break;
		}
	}
	if (!ok) {
    
    
		return true;
	}
	return false;
}
 
void solve() {
    
    
	cin >> n;
	for (int i = 1; i <= n; i++)
		cin >> a[i];
	if (check1()) {
    
    
		cout << "YES" << endl;
		return;
	}
	g1.clear();
	g2.clear();
	g1.push_back(0);
	g2.push_back(0);
	for (int i = 1; i <= n; i++) {
    
    
		if (a[i] != tag1) {
    
    
			g1.push_back(a[i]);
		}
		if (a[i] != tag2) {
    
    
			g2.push_back(a[i]);
		}
	}
	if (check2()) {
    
    
		cout << "YES" << endl;
	} else {
    
    
		cout << "NO" << endl;
	}
 
 
 
}
 
signed main() {
    
    
	int t;
	cin >> t;
	while (t--)
		solve();
 
}

C:使用useful algorithm(二分)
二分邀请的人数,在check中
设x为还需要邀请多少人才能满足条件
设have为已经邀请了多少人
如果第i个人的a[i].a >= x - 1 && a[i].b >= have
那么就选择他,并且x–,have++

#include <bits/stdc++.h>
#define int long long
using namespace std;
int n, m;
const int N = 2e5 + 10;
 
struct node {
    
    
	int a, b;
} a[N];
 
 
bool check(int x) {
    
    
	int sum = x;
	int have = 0;
	for (int i = 1; i <= n; i++) {
    
    
		if (a[i].a >= x - 1 && a[i].b >= have) {
    
    
			x--;
			have++;
		}
		if (have == sum)
			return true;
	}
	return false;
}
 
void solve() {
    
    
	cin >> n;
	for (int i = 1; i <= n; i++) {
    
    
		cin >> a[i].a >> a[i].b;
	}
	int l = 1, r = n ;
	int pre = 1e9;
	while (l < r) {
    
    
		int mid = l + r + 1 >> 1;
 
		if (check(mid)) {
    
    
			//cout << "true" << endl;
			l = mid ;
		} else {
    
    
			//cout << "false" << endl;
			r = mid - 1;
		}
	}
	cout << l << endl;
 
 
}
 
signed main() {
    
    
	ios::sync_with_stdio(false);
	int t;
	cin >> t;
	while (t--)
		solve();
 
}

おすすめ

転載: blog.csdn.net/fdxgcw/article/details/121532223