ABC355 A ~ D

A

可能写麻烦了,但是至少它对了。

#include <bits/stdc++.h>
#define gt getchar
#define pt putchar

typedef long long ll;
const int MAXN = 2e5 + 5;
const int mod = 998244353;

ll read() {
	ll x = 0, f = 1;char ch = gt();
	while (ch < '0' || ch > '9') {if (ch == '-') f = -1;ch = gt();}
	while (ch >= '0' && ch <= '9') {x *= 10;x += ch - '0';ch = gt();}
	return x * f;
}

ll a[5];

int main() {
	a[read()] = a[read()] = 1;
	ll res = 0;
	for (int i = 1; i <= 3; i++) {
		if(a[i] == 0) {
			if(res == 0) res = i;
			else {
				std::cout << -1;
				return 0;
			}
		}
	}
	std::cout << res;
	return 0;
}

B

\(f_i\) 表示 \(i\)\(a\) 中是否出现过。

搞到一起之后排序,判断即可。

#include <bits/stdc++.h>
#define gt getchar
#define pt putchar

typedef long long ll;
const int MAXN = 2e5 + 5;
const int mod = 998244353;

ll read() {
	ll x = 0, f = 1;char ch = gt();
	while (ch < '0' || ch > '9') {if (ch == '-') f = -1;ch = gt();}
	while (ch >= '0' && ch <= '9') {x *= 10;x += ch - '0';ch = gt();}
	return x * f;
}

ll a[MAXN], b[MAXN], c[MAXN];
bool f[MAXN];

int main() {
	ll n = read(), m = read();
	for (int i = 1; i <= n; i++) {
		a[i] = read();
		c[i] = a[i];
		f[a[i]] = true;
	}
	for (int i = 1; i <= m; i++) {
		b[i] = read();
		c[i + n] = b[i];
	}
	ll len = n + m;
	std::sort(c + 1, c + len + 1);
	for (int i = 1; i < len; i++) {
		if(f[c[i]] && f[c[i + 1]]) {
			puts("Yes");
			return 0;
		}
	}
	puts("No");
	return 0;
}

C

\(hang_i\) 表示第 \(i\) 行被涂的格子的个数。

\(lie_i\) 表示第 \(i\) 列被涂的格子的个数。

\(xie1,xie2\) 表示两条对角线上被涂的格子的个数。

行和列都好处理,对角线可以通过 \(O(n)\) 预处理。

#include <bits/stdc++.h>
#define gt getchar
#define pt putchar

typedef long long ll;
const int MAXN = 4e6 + 5;
const int mod = 998244353;

ll read() {
	ll x = 0, f = 1;char ch = gt();
	while (ch < '0' || ch > '9') {if (ch == '-') f = -1;ch = gt();}
	while (ch >= '0' && ch <= '9') {x *= 10;x += ch - '0';ch = gt();}
	return x * f;
}

ll hang[MAXN], lie[MAXN];
ll dui1, dui2;
bool f[MAXN], g[MAXN];
//f左上-右下对角线经过的数值
//g右上-坐下对角线经过的数值

int main() {
	ll n = read(), t = read();
	ll ans = 0;
	for (int i = 1; i <= n; i++) {
		f[(i - 1) * n + i] = true;
		g[i * n - i + 1] = true;
		//预处理
	}
	for (int i = 1; i <= t; i++) {
		ll a = read();
		if(ans) continue;
		ll nowhang;
		if(a % n == 0) nowhang = a / n;
		else nowhang = a / n + 1;
		ll nowlie;
		if(a % n != 0) nowlie = a % n;
		else nowlie = n;
		//当前这个数在第几行、第几列
		hang[nowhang]++;
		if(hang[nowhang] == n) {
			ans = i;
			continue;
		}
		lie[nowlie]++;
		if(lie[nowlie] == n) {
			ans = i;
			continue;
		}
		//边改变当前行的数值边判断
		if(f[a]) {
			dui1++;
			if(dui1 == n) {
				ans = i;
				continue;
			}
		}
		if(g[a]) {
			dui2++;
			if(dui2 == n) {
				ans = i;
				continue;
			}
		}
		//对角线
	}
	std::cout << (ans == 0 ? -1 : ans);
	return 0;
}

D

按照左端点排序,左端点相同就按照右端点排序。

枚举 \(1\sim n\),二分找到 \(i\) 后面的区间第一个 \(j\) 满足 \(l_j > r_i\),也就是这两个区间没有重合,把答案增加 \(j - 1 - i\)

不用考虑 \(i\) 前面的区间,因为在考虑位置 \(<i\) 的线段的时候已经考虑过了。

警钟长鸣,不要忘记删 std::cerr 调试语句!

#include <bits/stdc++.h>
#define gt getchar
#define pt putchar

typedef long long ll;
const int MAXN = 5e5 + 5;
const int mod = 998244353;

ll read() {
	ll x = 0, f = 1;char ch = gt();
	while (ch < '0' || ch > '9') {if (ch == '-') f = -1;ch = gt();}
	while (ch >= '0' && ch <= '9') {x *= 10;x += ch - '0';ch = gt();}
	return x * f;
}

ll n;
std::pair<ll, ll> a[MAXN];
ll c[MAXN];

int main() {
	n = read();
	for (int i = 1; i <= n; i++) {
		a[i].first = read();
		a[i].second = read();
	}
	std::sort(a + 1, a + n + 1);
	ll res = 0;
	for (int i = 1; i <= n; i++) c[i] = a[i].first;//为了方便二分,用 c 储存排序后的 l[i]
	for (int i = 1; i < n; i++) {
		ll p = std::upper_bound(c + i + 1, c + n + 1, a[i].second) - c;
		res += p - 1 - i;
	}
	std::cout << res << '\n';
	return 0;
}
posted @ 2024-05-25 22:53  ljlbj_fengyuwuzu  阅读(36)  评论(0编辑  收藏  举报