题目:
题目链接:https://codeforces.com/problemset/problem/356/A
有n个骑士,他们每个人都被从1-n进行编号,他们现在需要进行一次比赛,且总共会进行m场比赛。每场比赛会在编号在Li-Ri这段区间内的骑士之间举行,对于每场比赛,它的胜利者的编号为Xi,其他的骑士会出局,之后无法进行比赛。最后留下的骑士就是这次比赛的最终胜利者。比赛结束后,每个骑士都想知道他被哪一个骑士击败了,请你告诉他们。
(n,mleq 3 imes 10^5)。
思路
等价于每次把 ([l,x)∪(x,r]) 的为 (0) 的位置全部赋值为 (x)。
不难想到时光倒流,然后等价于线段树上区间推平。
时间复杂度 (O(mlog 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;
}