P4979 矿洞:坍塌
首先,这里提供的代码可能因为评测机波动而导致无法在不开 O2 下通过,但是开了 O2 后亲测不会出现问题。
现在步入正题。
很多人用了珂朵莉树,但是这题我给大家带来线段树套 bitset
的解法,这是以前的题解没有的。
事实上就是线段树每个点开一个 bitset
维护这个区间中出现了哪些数,那么显然当一个区间 bitset
中只有一个
bitset
很好求,其实只需把所有区间的 bitset
按位或即可,区间覆盖的话每个区间打一个标记即可。
但是由于 bitset
常数有些大,需要加各种卡常。
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <bitset>
#include <string>
using namespace std;
constexpr int N(5e5 + 5);
int n, m;
string k;
inline int read()
{
register char ch(getchar());
register int x(0);
while (ch < '0' || ch > '9') ch = getchar();
while (ch >= '0' and ch <= '9')
{
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
return x;
}
class SegmentTree
{
public:
struct Node
{
int l, r, tag;
bitset<3> s;
}tr[N << 2];
#define push_up(u) \
tr[u].s = tr[u << 1].s | tr[u << 1 | 1].s; \
#define push_down(u) \
if (tr[u].tag != -1) \
{ \
tr[u << 1].tag = tr[u].tag; \
tr[u << 1].s.reset(); \
tr[u << 1].s[tr[u].tag] = 1; \
tr[u << 1 | 1].tag = tr[u].tag; \
tr[u << 1 | 1].s.reset(); \
tr[u << 1 | 1].s[tr[u].tag] = 1; \
tr[u].tag = -1; \
} \
void build(register int u, register int l, register int r)
{
tr[u] = { l, r, -1 };
//tr[u].s.reset();
if (l == r)
{
tr[u].s[k[r - 1] - 'A'] = 1;
}
else
{
register int mid(l + r >> 1);
build(u << 1, l, mid);
build(u << 1 | 1, mid + 1, r);
push_up(u);
}
}
void update(register int u, register int l, register int r, register int k)
{
if (tr[u].l >= l and tr[u].r <= r)
{
tr[u].tag = k;
tr[u].s.reset();
tr[u].s[k] = 1;
}
else
{
push_down(u);
register int mid(tr[u].l + tr[u].r >> 1);
if (l <= mid) update(u << 1, l, r, k);
if (r > mid) update(u << 1 | 1, l, r, k);
push_up(u);
}
}
int query_node(register int u, register int x)
{
if (tr[u].l == x and tr[u].r == x)
{
if (tr[u].s[0]) return 0;
else if (tr[u].s[1]) return 1;
return 2;
}
push_down(u);
register int mid(tr[u].l + tr[u].r >> 1);
return (x <= mid ? query_node(u << 1, x) : query_node(u << 1 | 1, x));
}
bitset<3> query(register int u, register int l, register int r)
{
if (tr[u].l >= l and tr[u].r <= r) return tr[u].s;
push_down(u);
bitset<3> res;
res.reset();
register int mid(tr[u].l + tr[u].r >> 1);
if (l <= mid) res = query(u << 1, l, r);
if (r > mid) res |= query(u << 1 | 1, l, r);
return res;
}
};
SegmentTree sg;
int main()
{
n = read();
cin >> k;
sg.build(1, 1, n);
m = read();
while (m--)
{
register char c[2];
scanf("%s", &c[0]);
if (*c == 'A')
{
register int x(read()), y(read());
register char k[2];
scanf("%s", &k[0]);
sg.update(1, x, y, *k - 'A');
}
else
{
register int x(read()), y(read());
register bitset<3> q(sg.query(1, x, y));
if (q.count() > 1)
{
puts("No");
}
else
{
if (x == 1 || y == n) puts("Yes");
else
{
if (sg.query_node(1, x - 1) == sg.query_node(1, y + 1)) puts("No");
else puts("Yes");
}
}
}
}
return 0;
}
AC 记录 2.95s / 47.25MB / 2.81KB C++11
AC 记录 866ms / 47.27MB / 2.81KB C++11 O2
不开 O2,最慢的点 再也不用 bitset
了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现