C. Brackets Stack Query
合法括号序列需满足以下两个条件:
- 左右括号数相等
- 任意前缀中左括号数至少是右括号数
一般,我们遇到左括号,记为 +1,遇到右括号,记为 -1,然后维护前缀和。
那么,第一个条件就是 \(S_n = 0\),第二个条件就是 \(\min(S_i) = 0\)
在本题中,我们可以用一个栈来维护前缀和,遇到负数就将它变成 \(-\infty\),这样对于每次询问只需判定栈顶的元素是否为 \(0\) 即可
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
const int INF = 1001001001;
int main() {
int q;
cin >> q;
vector<int> x(1);
rep(qi, q) {
int type;
cin >> type;
if (type == 1) {
char c;
cin >> c;
int nx = x.back() + (c=='(' ? 1 : -1);
if (nx < 0) nx = -INF;
x.push_back(nx);
}
else {
x.pop_back();
}
if (x.back() == 0) puts("Yes");
else puts("No");
}
return 0;
}
D. 183184
记 \(y=C+x\)(题目里我们要枚举 \(x\in[1,D]\),等价于枚举 \(y\in(C,C+D]\))。
把 \(y\) 的十进制位数记为 \(d\)
把拼接写成数值形式:
因此,固定 \(d\)(即固定 \(y\) 的位数),当 \(y\) 遍历区间 \([10^{d-1},10^d-1]\) 时,\(f(C,y)\) 的取值正好是区间
于是问题变为:在这些区间中,有多少个整数是完全平方数?把所有位数的区间与 \((C, C+D]\) 的 \(y\)-范围相交后计数即可。
注意:取平方根可以用 long double 类型的 sqrtl 函数或写二分
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
// ll s(ll r) {
// ll ac = 0, wa = 2e9;
// while (ac+1 < wa) {
// ll wj = (ac+wa)/2;
// if (wj*wj <= r) ac = wj; else wa = wj;
// }
// return ac;
// }
ll s(ll r) {
return sqrtl(r);
}
ll s(ll l, ll r) {
return s(r) - s(l-1);
}
ll g(ll c, ll r) {
ll res = 0;
for (ll l = 1;; l *= 10) {
ll base = c*l*10;
ll nl = base+l, nr = base+(l*10-1);
nr = min(nr, base+r);
if (nr < nl) return res;
res += s(nl, nr);
}
}
void solve() {
ll c, d;
cin >> c >> d;
ll ans = g(c, c+d) - g(c, c);
cout << ans << '\n';
}
int main() {
int t;
cin >> t;
while (t--) solve();
return 0;
}
E. Farthest Vertex
经典结论:
距离每个点最远的点一定是直径两端点中的其中之一。
对于取编号最大的点,可以简单的用 std::pair<int, int> 维护 (深度,点的编号) 进行比较即可
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using P = pair<int, int>;
int main() {
int n;
cin >> n;
vector<vector<int>> to(n);
rep(i, n-1) {
int a, b;
cin >> a >> b;
--a; --b;
to[a].push_back(b);
to[b].push_back(a);
}
vector<P> ans(n);
auto dfs = [&](auto& f, int sv, int v, int p=-1, int d=0) -> P {
ans[v] = max(ans[v], P(d, sv));
P res(d, v);
for (int u : to[v]) {
if (u == p) continue;
res = max(res, f(f, sv, u, v, d+1));
}
return res;
};
int a = dfs(dfs, 0, 0).second;
int b = dfs(dfs, a, a).second;
dfs(dfs, b, b);
rep(v, n) cout << ans[v].second+1 << '\n';
return 0;
}
F. Pyramid Alignment
每个区間 \(i\) 的长度是固定的 \(W_i\)(且 \(W_1<W_2<\dots\))。任意时刻区間 \(i\) 可以由一个“锚点”和方向决定:
- 如果我们知道区間 \(i\) 的左端坐标为 \(a\),那么区間就是 \([a,\;a+W_i]\);
- 如果我们知道区間 \(i\) 的右端坐标为 \(b\),那么区間就是 \([b-W_i,\;b]\)。
用栈维护按索引单调划分的块——更新时从栈顶弹出失效块再压入新块以完成前缀对齐,查询则在栈上二分定位第一个包含目标点的索引并据此计算答案。
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using P = pair<int, int>;
struct B {
int l, x; char s;
};
int main() {
int n;
cin >> n;
vector<int> w(n);
rep(i, n) cin >> w[i];
int q;
cin >> q;
vector<B> bs;
bs.emplace_back(n, 0, 'L');
bs.emplace_back(0, 0, 'L');
auto get = [&](B b, int i) -> P {
if (b.s == 'L') return P(b.x, b.x+w[i]);
return P(b.x-w[i], b.x);
};
rep(qi, q) {
int type, x;
cin >> type >> x;
if (type == 3) {
int ac = 0, wa = bs.size();
while (ac+1 < wa) {
int wj = (ac+wa)/2;
auto [l, r] = get(bs[wj], bs[wj].l);
if (l <= x and x < r) ac = wj; else wa = wj;
}
int ans = n;
if (wa < bs.size()) {
int bi = wa;
ac = bs[bi].l; wa = bs[bi-1].l; // ac: not contain, wa: contain
while (ac+1 < wa) {
int wj = (ac+wa)/2;
auto [l, r] = get(bs[bi], wj);
if (l <= x and x < r) wa = wj; else ac = wj;
}
ans = n-wa;
}
cout << ans << '\n';
}
else {
x--;
if (x == 0) continue;
while (1) {
B b = bs.back(); bs.pop_back();
if (x < bs.back().l) {
bs.emplace_back(x, b.x, b.s);
break;
}
}
{
auto [l, r] = get(bs.back(), bs.back().l);
if (type == 1) bs.emplace_back(0, l, 'L');
else bs.emplace_back(0, r, 'R');
}
}
}
return 0;
}
G. Necklace
\(\mathrm{Burnside}\) 引理。
令序列长度为 \(N\),则群作用对应 \(N\) 种移位量。对于移位量 \(c\),不动的条件是:令 \(k:=\gcd(N,c), \; s:= \frac{N}{k}\),当把序列分成 \(k\) 个大小为
\(s\) 的组时,每个组内的元素都必须相同。对于每个 \(s\),通过 \(\mathrm{dp}\) 处理它对 \(f(2),…,f(U)\) 的贡献。
记 dp[i][j] 表示当前总乘积为 \(i\) 且已选 \(j\) 个元素时的方案数。
浙公网安备 33010602011771号