CF356A Knight Tournament

题目大意

n n n 个骑士,他们每个人都被从 1 − n 1-n 1n 进行编号。

他们现在需要进行一次比赛,且总共会进行 m m m 场比赛。

每场比赛会在编号在 L i − R i L_i-R_i LiRi 这段区间内的骑士之间举行,对于每场比赛,它的胜利者的编号为 X i X_i Xi,其他的骑士会出局,之后无法进行比赛。最后留下的骑士就是这次比赛的最终胜利者。

比赛结束后,每个骑士都想知道他被哪一个骑士击败了,请你告诉他们。

解题思路

首先可以想到, L i − R i L_i - R_i LiRi 所有人被 X i X_i Xi 击败。

那么可以用线段树将这一段标记为 X i X_i Xi

但是会有一个问题,如果一个数 o p op op,被多个区间包含,那么只能算被第一个区间击败。

所以将事件倒序处理即可。

时间复杂度 O ( m log ⁡ n ) \mathcal O(m \log n) O(mlogn)

CODE

#include <bits/stdc++.h>

using namespace std;

const int _ = 5e5 + 7;

int n, m;

int l[_], r[_], x[_];

int tr[_ << 2];

void push_down(int o)
{
	if(tr[o])
	{
		tr[o << 1] = tr[o];
		tr[o << 1 | 1] = tr[o];
		tr[o] = 0;
	}
}

void update(int o, int l, int r, int L, int R, int val)
{
	if(r < L || l > R) return;
	if(L <= l && r <= R)
	{
		tr[o] = val;
		return;
	}
	push_down(o);
	int mid = (l + r) >> 1;
	update(o << 1, l, mid, L, R, val);
	update(o << 1 | 1, mid + 1, r, L, R, val);
}

void print(int o, int l, int r)
{
	if(l == r)
	{
		cout << tr[o] << " ";
		return;
	}
	push_down(o);
	int mid = (l + r) >> 1;
	print(o << 1, l, mid);
	print(o << 1 | 1, mid + 1, r);
}

signed main()
{
	cin >> n >> m;
	for(int i = 1; i <= m; ++i) cin >> l[i] >> r[i] >> x[i];
	for(int i = m; i >= 1; --i)
	{
		if(x[i] == l[i])
		{
			update(1, 1, n, l[i] + 1, r[i], x[i]);
		}
		else if(x[i] == r[i])
		{
			update(1, 1, n, l[i], r[i] - 1, x[i]);
		}
		else
		{
			update(1, 1, n, l[i], x[i] - 1, x[i]);
			update(1, 1, n, x[i] + 1, r[i], x[i]);
		}
	}
	print(1, 1, n);
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值