Educational Codeforces Round 160 (Rated for Div. 2)

A#

直接模拟,注意细节

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

using namespace std;

ll p[15] = {1};

void solve() {
	ll x;
	cin >> x;
	int len = 0;
	while(x / p[len + 1]) ++ len;
	for(int i = 1; i <= len; ++ i) {
		ll a = x / p[i];
		ll b = x % p[i];
		if(b >= p[i - 1] && b > a) {
			return cout << a << ' ' << b << '\n', void();
		}
	}
	cout << "-1\n";
}

int main() {
	for(int i = 1; i <= 10; ++ i) p[i] = p[i - 1] * 10;
	int T;
	cin >> T;
	while(T --) solve();
	return 0;
}

B#

一道很直观的贪心,用总共的0和1去构造答案,一旦失败,输出答案

void solve() {
	string s;
	cin >> s;
	int cnt[2] = {0, 0};
	for(auto ch : s) cnt[1] += ch == '1', cnt[0] += ch == '0';
	for(int i = 0; i < s.length(); ++ i) {
		if(s[i] == '0') {
			if(-- cnt[1] < 0) return cout << s.length() - i << '\n', void();
		} 
		else if(-- cnt[0] < 0) {
			return cout << s.length() - i << '\n', void();
		}
	}
	cout << "0\n";
}

C#

开一个f数组统计某一位出现的次数
注意第i位能被两个i1位合成
检验时从低到高位遍历,同时计算f数组内部低位对高位的贡献

#include<bits/stdc++.h>

using namespace std;

int f[40], g[40];

bool check(int x) {
	memcpy(g, f, sizeof f);
	for(int i = 0; i <= 30; ++ i) {
		if(x >> i & 1) {
			if(g[i]) {
				g[i + 1] += (g[i] - 1) / 2;
			}
			else return 0;
		}
		else g[i + 1] += g[i] / 2; 
	}
	return 1;
}

int main() {
	ios :: sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
	int m;
	cin >> m;
	while(m --) {
		int op, x;
		cin >> op >> x;
		if(op == 1) ++ f[x];
		else {
			cout << (check(x) ? "YES" : "NO") << '\n';
		}
	}
	return 0;
}

D. Array Collapse#

考虑分治。

f[l,r] 为区间 [l,r] 能够通过操作得到的子序列数。

[l,r] 内最小元素的下标为 p

如果只考虑 [l,r] 内部的所有情况,因为无论怎么操作 a[p] 都无法被删除,所以有 f[l][r]=f[l][p1]f[p+1][r]

考虑外部元素对 f[l][r] 的贡献。

显然,任意一个比 a[p] 大的数都不能使 [l,r] 内有新的子序列出现。

如果 i<la[i]<a[p],那么我们可以把 [l,p] 删掉,剩下 [p+1,r],新贡献为 f[p+1][r]

如果 j>ra[j]<a[p],那么我们可以把 [p,r] 删掉,剩下 [l,p1],新贡献为 f[l][p1]

如果上述 i,j 都存在,我们发现两者重复计算了 [l,r] 全部删掉的方案,则 f[l][r] 减一。

考虑递归边界。

如果 l>r,只存在空集这一种方案。

如果 l=r 且左右两边至少有一个小于 a[l] 的元素,则有 ϕa[l] 两种,否则只有 a[l] 一种。

code#

其中 f[i][j] 存的是 [i,i+(1<<j)1] 内最小元素的位置。

L_less 表示左边是否存在比区间最小值小的元素,R_less 表示右边是否存在比区间最小值小的元素。

void init() {
	for(int i = 1; i <= n; ++ i) f[i][0] = i;
	for(int j = 1; j < 20; ++ j) {
		for(int i = 1; i + (1 << j) - 1 <= n; ++ i) {
			if(a[f[i][j - 1]] < a[f[i + (1 << j - 1)][j - 1]]) f[i][j] = f[i][j - 1];
			else f[i][j] = f[i + (1 << j - 1)][j - 1];
		}
	}
}

int get_pos(int l, int r) {
	int len = log2l(r - l + 1);
	if(a[f[l][len]] < a[f[r - (1 << len) + 1][len]]) return f[l][len];
	else return f[r - (1 << len) + 1][len];
}

ll get_val(int l, int r, bool L_less, bool R_less) {
	if(l > r) return 1;
	if(l == r && (L_less || R_less)) return 2;
	if(l == r) return 1;
	
	int p = get_pos(l, r);
	ll left = get_val(l, p - 1, L_less, true);
	ll right = get_val(p + 1, r, true, R_less);
	
	ll ret = left * right % P;
	if(L_less) ret += right;
	if(R_less) ret += left;
	if(L_less && R_less) -- ret;
	return (ret % P + P) % P;
}

void solve() {
	cin >> n;
	for(int i = 1; i <= n; ++ i) cin >> a[i];
	init();
	cout << get_val(1, n, 0, 0) << '\n';
}
posted @   Lu_xZ  阅读(97)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示