AtCoder Beginner Contest 403 题解

A - Odd Position Sum

略。

#include <bits/stdc++.h>
#define int long long
using namespace std;
signed main() {
	int n; cin >> n;
	vector<int> a(n + 1);
	int res = 0;
	for (int i = 1; i <= n; i ++) cin >> a[i];
	for (int i = 1; i <= n; i ++) {
		if (i & 1) 
			res += a[i];
	}
	cout << res;
	return 0;
}

B - Four Hidden

注意细节。(你肯定不想吃 7 发罚时吧)

#include <bits/stdc++.h>
#define int long long
using namespace std;
string T, U;

signed main() {
	cin >> T >> U;
	int lenT = T.size(), lenU = U.size();
	T = " " + T, U = " " + U;
	int cntT = 0, cntU = 0;
	for (int i = 1; i <= lenT; i ++)
		cntT += (T[i] == '?');
	if (cntT == lenT) {
		cout << "Yes\n";
		return 0;
	}
	for (int i = 1; i <= lenT; i ++) {
		for (int j = 1; j <= lenU; j ++) {
			if (T[i] == U[j]) {
//				cout << i << " " << j << endl;
				bool tag1 = true, tag2 = true;
				int k = 0;
				for (k = i + 1; k <= lenT; k ++){
					int dlt = abs(i - k);
					if (j + dlt > lenU) break;
					if (T[k] != U[j + dlt]) {
//						cout << T[k] << " " << U[j + dlt] << "\n";
						if (T[k] != '?') { tag1 = false; break; }
					}
				}
				if (k - i != lenU - j + 1) tag1 = false;
				for (k = i - 1; k >= 1; k --) {
					int dlt = abs(i - k);
					if (j - dlt < 1) break;
					if (T[k] != U[j - dlt]) {
//						cout << T[k] << " " << U[j - dlt] << "\n";
						if (T[k] != '?') { tag2 = false; break; }
					}
				}
				if (i - k != j) tag2 = false;
				if (tag1 && tag2) {
					cout << "Yes\n";
					return 0;
				}
			}
		}
	}
	if (lenU <= 4) {
		for (int i = 1; i <= lenT; i ++) {
			if (T[i] == '?') {
				int cnt = 1;
				for (int j = i + 1; j <= lenT; j ++) {
					if (T[j] != '?') break;
					++cnt;
				}
				if (cnt >= lenU) {
					cout << "Yes\n";
					return 0;
				}
			}
		}
	}
	cout << "No\n";
	return 0;
}

C - 403 Forbidden

gp_hash_table 直接做,全部可以访问另打 \(tag_x\) 标记。

#include <bits/extc++.h>
#define int long long
using namespace std;
const int MAXN = 2e5 + 10;
int N, M, Q, opt, X, Y;
bool tag[MAXN];
__gnu_pbds::gp_hash_table<int,bool> mp[MAXN];

signed main() {
	ios_base::sync_with_stdio (false);
	cin.tie (nullptr), cout.tie (nullptr);
	cin >> N >> M >> Q;
	for (int i = 1; i <= Q; i ++) {
		cin >> opt;
		if (opt == 1) {
			cin >> X >> Y;
			mp[X][Y] = true;
		} else if (opt == 2) {
			cin >> X, tag[X] = true;
		} else {
			cin >> X >> Y;
			if (mp[X][Y] || tag[X]) 
				cout << "Yes\n";
			else
				cout << "No\n";
		}
	}
	return 0;
}

D - Forbidden Difference

观察到 \(D\) 很小,考虑枚举值域。

你发现对于一个数 \(x\) 是否被删取决于 \(x+d,x+2d,\dots\) 的存在性,如果说选择删 \(x\),后面随便,反之后面必删。

\(f_{i,0/1}\) 表示数 \(i\) 是否被删的最小答案,你发现这就是个类似树上最大独立集的问题。

\[f_{now,0} \leftarrow f_{lst,1} \\ f_{now,1} \leftarrow \min(f_{lst,0},f_{lst,1}) \]

直接枚举 \(D\) 的倍数即可。

#include <bits/stdc++.h>
#define int long long

using namespace std;
const int MAXN = 1e6 + 10;

int N, D, mxVal, ans;
int a[MAXN], bu[MAXN], f[MAXN][2];

signed main() {
	ios_base::sync_with_stdio (false);
	cin.tie (nullptr), cout.tie (nullptr);
	cin >> N >> D, mxVal = -1;
	for (int i = 1; i <= N; i ++) {
		cin >> a[i], bu[a[i]] ++;
		mxVal = max (mxVal, a[i]);
	}
	if (!D) {
		for (int i = 1; i <= N; i ++)
			ans += bu[a[i]] - 1, bu[a[i]] = 1;
		cout << ans << "\n";
		return 0;
	}
	for (int i = 0; i < D; i ++) {
		f[i][1] = bu[i];
		for (int j = 1; i + D * j <= mxVal; j ++) {
			int now = i + D * j, lst = i + D * (j - 1);
			if (bu[now]) {
				f[now][1] = min (f[lst][1], f[lst][0]) + bu[now];
				f[now][0] = f[lst][1];
			} else {
				f[now][1] = f[now][0] = min (f[lst][1], f[lst][0]);
			}
			if (i + D * (j + 1) > mxVal) {
				ans += min (f[now][1], f[now][0]);
				break;
			}
		}
	}
	cout << ans << "\n";
	return 0;
}

G - Odd Position Sum Query

Statement

\(q\) 次添加操作,每次向序列尾添加一个数 \(y\),每次求排序后序列奇数位的和,强制在线。

Solution

一眼想到分块暴力重构,但是 \(N \leq 3\times 10^5\),原地起飞。

实际上可以动开值域线段树做,记录当前序列长度 \(len\),每次加入一个数都会改变 \(len\) 的奇偶性,那么我们再记 \(odd\) 为奇数位和,\(even\) 为偶数位和,那么每次只需要单点修改,如果说修改前 \(len\) 为偶,那么修改奇数位和,反之同理,上传的时候合并左右儿子也要判一下合并之后的长度奇还是偶的情况。

Code

#include <bits/stdc++.h>
#define int long long

using namespace std;
const int MAXN = 300010;
const int MAXS = 12000010;
const int MOD = 1000000000;

int Q, idx, lst, now;

struct Sgton {
	int lfts = -1;
	int rgts = -1;
	int len, odd, even;
} Sgt[MAXS];

void update (int l, int r, int rt, int p) {
	if (l == r) {
		if (!(Sgt[rt].len & 1)) 
			Sgt[rt].odd += p;
		else
			Sgt[rt].even += p;
		++Sgt[rt].len;
		return;
	}
	
	int mid = (l + r) >> 1;
	
	if (p <= mid) {
		if (!~Sgt[rt].lfts)
			Sgt[rt].lfts = ++idx;
		
		update (l, mid, Sgt[rt].lfts, p);
	} else {
		if (!~Sgt[rt].rgts)
			Sgt[rt].rgts = ++idx;
		
		update (mid + 1, r, Sgt[rt].rgts, p);
	}
	
	Sgt[rt].len = 0;
	Sgt[rt].odd = 0;
	Sgt[rt].even = 0;
	
	if (~Sgt[rt].lfts) {
		Sgt[rt].len = Sgt[Sgt[rt].lfts].len;
		Sgt[rt].odd = Sgt[Sgt[rt].lfts].odd;
		Sgt[rt].even = Sgt[Sgt[rt].lfts].even;
	}
	if (~Sgt[rt].rgts) {
		if (!(Sgt[rt].len & 1)) {
			Sgt[rt].odd += Sgt[Sgt[rt].rgts].odd;
			Sgt[rt].even += Sgt[Sgt[rt].rgts].even;
		} else {
			Sgt[rt].odd += Sgt[Sgt[rt].rgts].even;
			Sgt[rt].even += Sgt[Sgt[rt].rgts].odd;
		}
		Sgt[rt].len += Sgt[Sgt[rt].rgts].len;
	}
	
	return;
}

signed main() {
	scanf ("%lld", &Q);
	
	while (Q--) {
		scanf ("%lld", &now);
		now = (now + lst) % MOD + 1;
		
		update (1, MOD, 0, now), lst = Sgt[0].odd;
		printf ("%lld\n", lst);
	}
	return 0;	
}
posted @ 2025-04-28 15:55  xAlec  阅读(131)  评论(0)    收藏  举报