1. 程式人生 > 其它 >CF356A Knight Tournament

CF356A Knight Tournament

題目大意

\(n\) 個騎士,他們每個人都被從 \(1-n\) 進行編號。

他們現在需要進行一次比賽,且總共會進行 \(m\) 場比賽。

每場比賽會在編號在 \(L_i-R_i\) 這段區間內的騎士之間舉行,對於每場比賽,它的勝利者的編號為 \(X_i\),其他的騎士會出局,之後無法進行比賽。最後留下的騎士就是這次比賽的最終勝利者。

比賽結束後,每個騎士都想知道他被哪一個騎士擊敗了,請你告訴他們。

解題思路

首先可以想到,\(L_i - R_i\) 所有人被 \(X_i\) 擊敗。

那麼可以用線段樹將這一段標記為 \(X_i\)

但是會有一個問題,如果一個數 \(op\),被多個區間包含,那麼只能算被第一個區間擊敗。

所以將事件倒序處理即可。

時間複雜度 \(\mathcal O(m \log n)\)

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;
}

本文來自部落格園,作者:蒟蒻orz,轉載請註明原文連結:https://www.cnblogs.com/orzz/p/15553529.html