专栏文章
数据结构
个人记录参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @minivs64
- 此快照首次捕获于
- 2025/12/02 03:08 3 个月前
- 此快照最后确认于
- 2025/12/02 03:08 3 个月前
P14172 【MX-X23-T2】括号串
错因:思路细节错误,有可能虽然相邻两个是
)(,但是可能原本就是匹配的,改了之后反倒不匹配了。思路:当遇到
C( 时,将他压进栈,否则,若栈内还有未匹配的括号,则 stk.pop(),再否则,判断是否用过一次机会,是的话就无解,否则使用一次机会。#include <bits/stdc++.h>
using namespace std;
int t, n;
string s;
void work() {
cin >> n >> s;
bool f = 0;
stack<char> stk;
for (int i = 0; i < s.size(); i++) {
if (s[i] == '(')
stk.push(s[i]);
else if (!stk.empty() && stk.top() == '(')
stk.pop();
else if (f) {
cout << "No\n";
return;
} else {
f = 1;
stk.push(s[i + 1]);
s[i + 1] = s[i];
}
}
if (stk.empty()) {
cout << "Yes\n";
} else {
cout << "No\n";
}
}
signed main() {
cin >> t;
while (t--) {
work();
}
return 0;
}
P1020 [NOIP 1999 提高组] 导弹拦截
第一问:求最长不上升子序列长度。
第二问:求要多少个不上升子序列才能覆盖原数组——即最长上升子序列的长度。
对于 , 的方法只有一半分数,考虑树状数组优化 。
树状数组存储比 小的最大 值。
对于第一问,我们可以把它当成最长后缀不下降子序列。
状态: 表示后面 个数的最长后缀不下降子序列长度。
答案:。
状态转移方程:。
初始化:。
对于第二问,我们可以把它当成最长上升子序列。
状态: 表示前 个数的最长上升子序列长度。
答案:。
状态转移方程:,因为是严格上升。
初始化:。
CPP#include <bits/stdc++.h>
using namespace std;
int dp[100005], a[100005], tr[400005];
int lowbit(int x) {
return x & (-x);
}
void modify(int x, int val) {
while (x <= 5e4) {
tr[x] = max(tr[x], val);
x += lowbit(x);
}
}
int query(int x) {
int maxn = 0;
while (x) {
maxn = max(maxn, tr[x]);
x -= lowbit(x);
}
return maxn;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int n = 1;
for (; cin >> a[n]; n++) {
dp[n] = 1;
}
n--;
for (int i = n; i >= 1; i--) {
dp[i] = query(a[i]) + 1;
modify(a[i], dp[i]);
}
cout << *max_element(dp + 1, dp + 1 + n) << '\n';
memset (tr, 0, sizeof tr);
memset (dp, 0, sizeof dp);
for (int i = 1; i <= n; i++) {
dp[i] = query(a[i] - 1) + 1;
modify(a[i], dp[i]);
}
cout << *max_element(dp + 1, dp + 1 + n);
return 0;
}
CF547B Mike and Feet
若用暴力枚举 + 数据结构会 T,考虑单调栈 + 单调性优化。
- 考虑每个 成为最小值的贡献;
- 对于某个最小值 ,若可以在长度为 的区间内成为最小值,那么在长度在 的所有长度的区间都可以成为最小值,从而参与对于长度区间的最大值竞争;
- 预处理 成为最小值的最长区间,显然用单调栈维护;
- 维护 表示 成为最小值的最小下标和最大下标;
- ;
- 倒序枚举区间长度 从 到 ,。
#include <bits/stdc++.h>
using namespace std;
int n, a[2000005], r[200005], l[200005], ans[2000005];
stack<int> s;
signed main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
for (int i = 1; i <= n; i++) {
while (!s.empty() && a[i] < a[s.top()]) {
r[s.top()] = i;
s.pop();
}
s.push(i);
}
while (!s.empty()) {
r[s.top()] = n + 1;
s.pop();
}
for (int i = n; i >= 1; i--) {
while (!s.empty() && a[i] < a[s.top()]) {
l[s.top()] = i;
s.pop();
}
s.push(i);
}
while (!s.empty()) {
l[s.top()] = 0;
s.pop();
}
for (int i = 1; i <= n; i++) {
ans[r[i] - 1 - (l[i] + 1) + 1] = max(ans[r[i] - 1 - (l[i] + 1) + 1], a[i]);
}
for (int i = n; i >= 1; i--) {
ans[i] = max(ans[i], ans[i + 1]);
}
for (int i = 1; i <= n; i++) {
cout << ans[i] << ' ';
}
return 0;
}
P12347 [蓝桥杯 2025 省 A 第二场] 栈与乘积
考虑线段树。
前两个操作都是单点修改,后一个操作是区间查询。
其中,第二个操作就相当于把 点设成 。
若两数相乘超过 ,则将其赋为 ,这样方便分辨。
CPP#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5 + 5, M = 1ll << 32;
int tree[4 * N], q, top = 0;
int Mul(int x, int y) {
if (x == 0 || y == 0)
return 0;
if (x == -1 || y == -1)
return -1;
if (x * y >= M)
return -1;
return x * y;
}
void push_up(int u, int l, int r) {
tree[u] = Mul(tree[2 * u], tree[2 * u + 1]);
return;
}
void build(int u, int l, int r) {
if (l == r) {
tree[u] = 1;
return;
}
int mid = (l + r) >> 1;
build(2 * u, l, mid);
build(2 * u + 1, mid + 1, r);
push_up(u, l, r);
return;
}
int query(int u, int l, int r, int X, int Y) {
if (Y < l || r < X)
return 1;
if (X <= l && r <= Y)
return tree[u];
int mid = (l + r) >> 1;
int tmp1 = query(2 * u, l, mid, X, Y);
int tmp2 = query(2 * u + 1, mid + 1, r, X, Y);
return Mul(tmp1, tmp2);
}
void update(int u, int l, int r, int X, int val) {
if (X < l || r < X)
return;
if (X == l && r == X) {
tree[u] = val;
return;
}
int mid = (l + r) >> 1;
update(2 * u, l, mid, X, val);
update(2 * u + 1, mid + 1, r, X, val);
push_up(u, l, r);
return;
}
signed main() {
cin >> q;
build(1, 1, q);
for (int i = 1; i <= q; i++) {
int op, x, y;
cin >> op;
if (op == 1) {
cin >> x;
top++;
update(1, 1, q, top, x);
} else if (op == 2) {
if (top > 0)
update(1, 1, q, top--, 1);
} else {
cin >> y;
if (y > top) {
cout << "ERROR\n";
} else {
int tmp = query(1, 1, q, top - y + 1, top);
if (tmp <= -1)
cout << "OVERFLOW\n";
else
cout << tmp << "\n";
}
}
}
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...