题目大意
一些骑士打架,输了就淘汰,输出一个数组,表示第i个人是被a[i]淘汰的。
因为涉及到区间的修改,不可避免的想到了线段树,可惜菜鸡只会用区间加的板子,这种值替换的线段树不会写,菜哭了。
还是一手正难则反,考虑倒着处理每一次战斗,这样可以覆盖之前的的修改。
代码
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=(3e5+7)*4;
struct node{
int l,r;
int tag;
int v;
} t[maxn];
void build(int l,int r,int k){
t[k].l=l;
t[k].r=r;
t[k].tag=0;
t[k].v=0;
if(l==r) return ;
int mid = (t[k].l+t[k].r)/2;
build(l,mid,k*2);
build(mid+1,r,k*2+1);
}
void pushdown(int k){
if(t[k].tag){
t[k*2].tag=t[k*2+1].tag=t[k].tag;
t[k*2].v=t[k*2+1].v=t[k].tag;
t[k].tag=0;
}
}
void update(int l,int r,int k,int v){
if(t[k].l==l&&t[k].r==r){
t[k].v=v;
t[k].tag=v;
return ;
}
pushdown(k);
int mid=(t[k].l+t[k].r)/2;
if(r<=mid)update(l,r,k*2,v);
else if(l>mid)update(l,r,k*2+1,v);
else{
update(l,mid,k*2,v);
update(mid+1,r,k*2+1,v);
}
}
struct edge{
int l,r,x;
} q[maxn/4];
int query(int x,int k){
if(t[k].l==t[k].r)return t[k].v;
pushdown(k);
int mid=(t[k].l+t[k].r)/2;
if(x<=mid) return query(x,k*2);
else return query(x,k*2+1);
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=0; i<m; i++){
scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].x);
}
build(1,n,1);
for(int i=m-1; i>=0; i--){
if(q[i].l!=q[i].x)//如果不是胜者在最右边的情况
update(q[i].l,q[i].x-1,1,q[i].x);
if(q[i].r!=q[i].x)//如果不是胜者在最左边的情况
update(q[i].x+1,q[i].r,1,q[i].x);
}
int temp=query(1,1);
if(temp==1)printf("0");
else printf("%d",temp);
for(int i=2; i<=n; i++){
int temp=query(i,1);
printf(" %d",temp==i?0:temp);
}
return 0;
}