【CF356A】Knight Tournament

题目:

题目链接:https://codeforces.com/problemset/problem/356/A
有n个骑士,他们每个人都被从1-n进行编号,他们现在需要进行一次比赛,且总共会进行m场比赛。每场比赛会在编号在Li-Ri这段区间内的骑士之间举行,对于每场比赛,它的胜利者的编号为Xi,其他的骑士会出局,之后无法进行比赛。最后留下的骑士就是这次比赛的最终胜利者。比赛结束后,每个骑士都想知道他被哪一个骑士击败了,请你告诉他们。
\(n,m\leq 3\times 10^5\)

思路

等价于每次把 \([l,x)∪(x,r]\) 的为 \(0\) 的位置全部赋值为 \(x\)
不难想到时光倒流,然后等价于线段树上区间推平。
时间复杂度 \(O(m\log n)\)

代码

#include <bits/stdc++.h>
using namespace std;

const int N=300010;
int n,m,L[N],R[N],X[N];

struct SegTree
{
	int tag[N*4];
	
	void pushdown(int x)
	{
		if (tag[x])
		{
			tag[x*2]=tag[x*2+1]=tag[x];
			tag[x]=0;
		}
	}
	
	void update(int x,int l,int r,int ql,int qr,int v)
	{
		if (l>=ql && r<=qr) { tag[x]=v; return; }
		pushdown(x);
		int mid=(l+r)>>1;
		if (ql<=mid) update(x*2,l,mid,ql,qr,v);
		if (qr>mid) update(x*2+1,mid+1,r,ql,qr,v);
	}
	
	void query(int x,int l,int r)
	{
		if (l==r) { printf("%d ",tag[x]); return; }
		pushdown(x);
		int mid=(l+r)>>1;
		query(x*2,l,mid); query(x*2+1,mid+1,r);
	}
}seg;

int main()
{
	scanf("%d%d",&n,&m);
	for (int i=1;i<=m;i++)
		scanf("%d%d%d",&L[i],&R[i],&X[i]);
	for (int i=m;i>=1;i--)
	{
		int l=L[i],r=R[i],x=X[i];
		if (x>l) seg.update(1,1,n,l,x-1,x);
		if (x<r) seg.update(1,1,n,x+1,r,x);
	}
	seg.query(1,1,n);
	return 0;
}
posted @ 2021-02-02 10:22  stoorz  阅读(56)  评论(0编辑  收藏  举报