题目大意
有 n n n 个骑士,他们每个人都被从 1 − n 1-n 1−n 进行编号。
他们现在需要进行一次比赛,且总共会进行 m m m 场比赛。
每场比赛会在编号在 L i − R i L_i-R_i Li−Ri 这段区间内的骑士之间举行,对于每场比赛,它的胜利者的编号为 X i X_i Xi,其他的骑士会出局,之后无法进行比赛。最后留下的骑士就是这次比赛的最终胜利者。
比赛结束后,每个骑士都想知道他被哪一个骑士击败了,请你告诉他们。
解题思路
首先可以想到, L i − R i L_i - R_i Li−Ri 所有人被 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;
}