CF356A Knight Tournament

题意

给定一个初始值全为 00 的序列 aa,有 qq 次操作,每次指定一三个数 l,r,xl, r, x,表示将 alax1a_l \sim a_{x-1}ax+1ara_{x+1} \sim a_r 中每个数设为 aia_i,对于每个数,若 ai=0a_i=0aixa_i \leftarrow x,否则不变。最后要求输出 aa

解法

并查集就不要了,这种题就应该线段树。

区间覆盖裸题,提供一个以前题解没有的在线的线段树写法,不需要操作倒序。

考虑对于每一个节点维护一个 tagtag,表示这个区间被赋值成了 tagtag,那么只需要在下传操作时不抹掉父节点的 tagtag,同时仅当左右儿子的 tag=0tag = 0 时才对左右儿子下传。

当然倒序也是可以的,就是对操作倒序,这样保证每个点修改都是正序时最先的,也就是倒序时最晚的。

代码:

#pragma GCC optimize("-Ofast")
#pragma unroll 10
#include <iostream>
#include <cstdio>
using namespace std;

const int N = 3e5 + 5;

int n, q;

class SegmentTree
{
public:
	struct Node
	{
		int l, r, sum, tag;
	}tr[N << 2];
	void push_up(int u)
	{
		tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
	}
	void push_down(int u)
	{
		auto& root = tr[u], &left = tr[u << 1], &right = tr[u << 1 | 1];
		if (root.tag)
		{
			if (!left.tag)
			{
				left.tag = root.tag;
				left.sum = (left.r - left.l + 1) * root.tag;
			}
			if (!right.tag)
			{
				right.tag = root.tag;
				right.sum = (right.r - right.l + 1) * root.tag;
			}
		}
	}
	void build(int u, int l, int r)
	{
		tr[u] = { l, r, 0, 0 };
		if (l == r) return;
		int mid = l + r >> 1;
		build(u << 1, l, mid);
		build(u << 1 | 1, mid + 1, r);
	}
	void update(int u, int l, int r, int k)
	{
		if (tr[u].tag) return;
		if (tr[u].l >= l and tr[u].r <= r)
		{
			tr[u].tag = k;
			tr[u].sum = (tr[u].r - tr[u].l + 1) * k;
		}
		else
		{
			push_down(u);
			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(int u, int x)
	{
		if (tr[u].l == x && tr[u].r == x) return tr[u].sum;
		push_down(u);
		int mid = tr[u].l + tr[u].r >> 1;
		return (x <= mid ? query_node(u << 1, x) : query_node(u << 1 | 1, x));
	}
};

SegmentTree seg;

int main()
{
	scanf("%d%d", &n, &q);
	seg.build(1, 1, n);
	for (int i = 1; i <= q; i++)
	{
		int l, r, x;
		scanf("%d%d%d", &l, &r, &x);
		int lp = l, rp = x - 1, lg = x + 1, rg = r;
		if (lp <= rp) seg.update(1, lp, rp, x);
		if (lg <= rg) seg.update(1, lg, rg, x);
	}
	for (int i = 1; i <= n; i++) printf("%d ", seg.query_node(1, i));
	puts("");
	return 0;
}
posted @   HappyBobb  阅读(7)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示