P4979 矿洞:坍塌

首先,这里提供的代码可能因为评测机波动而导致无法在不开 O2 下通过,但是开了 O2 后亲测不会出现问题。

现在步入正题。

很多人用了珂朵莉树,但是这题我给大家带来线段树套 bitset 的解法,这是以前的题解没有的。

事实上就是线段树每个点开一个 bitset 维护这个区间中出现了哪些数,那么显然当一个区间 [l,r][l, r] 满足要求当且仅当 al,al+1,,ara_l, a_{l+1}, \cdots, a_r 维护的 bitset 中只有一个 11,且 al1a_{l-1}ar+1a_{r+1} 数不同。

al,al+1,,ara_l, a_{l+1}, \cdots, a_r 维护的 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,最慢的点 997997 毫秒。再也不用 bitset 了。

posted @   HappyBobb  阅读(14)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示