Atcoder Beginner Contest 428 补题记录
C. Brackets Stack Query
题目大意
给予你 1 个空的字符串与 \(q\) 个询问,形如 1 ( 的询问将在字符串后增加 1 个 ( 字符,形如 2 的询问将会移除最后 1 个字符。在每次询问之后,你需要回答当前字符串中的左右括号是否能恰好匹配。
解法
性质:让我们假定存在 1 个只含有 ( 和 ) 的字符串 \(S\) ,再假定 1 个数组 \(A\) ,其中 \(A_0 = 0\) 且 \(A_i = A_{i-1} + S_i\) ,在这里我们认为, '(' = 1 ,同时 ')' = -1 。可以容易看出当 \(A_{|S|}=0\) 时,左右括号数量是相等的。同时,也容易发现如果 \(A\) 中有小于 0 的项,则一定有某个时刻右括号多于左括号。一旦这种情况发生,无论后面补上了多少左括号都没法做到匹配。
因此,我们要动态维护一个支持 \(O( 1)\) 入栈,出栈和查询栈内最小值的数据结构。这里采用第二个栈来保存历史上每个时刻的最小值,这样就可以在出栈后进行还原。也就是在第二个栈入栈时要和栈顶比较,如果小于栈顶直接入栈,如果大于栈顶就将栈顶再次入栈。在出栈时,两个栈顶同时出栈。这样,第二个栈的栈顶就一直维护了第一个栈的最小值数据。
代码实现
具体实现上,由于 cin 和 cout 常数很大,需要优化一下,否则会 TLE。
#include <bits/stdc++.h>
#define pb push_back
#define ob pop_back
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 5;
const int mod = 1e9 + 7;
ll q;
int main() {
cin.tie(0) -> sync_with_stdio(0);
cin >> q;
vector<int> A{0}, B{0};
for(int i = 1; i <= q; i ++) {
int op = 0;
cin >> op;
if(op == 1) {
char c;
cin >> c;
A.pb(A.back() + (c == '(' ? 1 : -1));
B.pb(min(A.back(), B.back()));
} else {
A.ob();
B.ob();
}
cout << ((A.back() == 0 && B.back() == 0) ? "Yes" : "No") << '\n';
}
}
D. 183184
题目大意
定义函数 \(f(x,y)\) 就是将 \(x\) 和 \(y\) 两个数前后拼接在一起。现在给你 2 个正整数 \(C,D\) ,找到满足下列 2 个条件的正整数 \(x\) 的个数。
- \(1\le x \le D\)
- \(f(C, C+x)\) 为完全平方数
解法
假定 \(C +x\) 共有 \(d\) 位,那么 \(x\) 必须要满足:
- \(1\le x \le D\)
- \(10^{d-1}-C\le x\le 10^d - 1 -C\)
那么容易定义 \(x\) 的上下界:\(L = \max(1, 10^{d-1} - C)\) ,\(R=\min(10^d-1-C, D)\).
因为我们已经假定了 \(C +x\) 共有 \(d\) 位,因此在这个条件下,题目要求的完全平方数的取值范围在 \([\ C\times 10^d + C +L\ ,C\times10^{d} + C + R\ ]\) .
一个结论是,总共有 \(\lfloor \sqrt{k} \rfloor\) 个小于 \(k\) 的完全平方数,因此在 \(d\) 位的条件下满足条件的答案的个数应当是 \(\lfloor\sqrt{C\times10^{d} + C + R}\rfloor -\lfloor\sqrt{\ C\times 10^d + C +L-1}\rfloor\) .
现在只需要求出每个可能的 \(d\) 的答案之和就可以了。
代码实现
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll t, c, d;
ll f (ll x) {
ll y = sqrt(x);
while (y * y > x) y--;
while ((y + 1) * (y + 1) <= x) y++;
return y;
}
void solve() {
cin >> c >> d;
ll ans = 0;
ll xmin = 1, xmax = 9, cshift = 10;
while(xmin <= c + d) {
ll l = max(xmin, c + 1);
ll r = min(xmax, c + d);
if(l <= r) {
ll vl = c * cshift + l;
ll vr = c * cshift + r;
ans += f(vr) - f(vl - 1);
}
xmin *= 10;
xmax = (xmax + 1) * 10 - 1;
cshift *= 10;
}
cout << ans << endl;
}
int main() {
cin.tie(0) -> sync_with_stdio(0);
cin >> t;
while(t --) {
solve();
}
}

浙公网安备 33010602011771号