CodeForces - 356A Knight Tournament(线段树,或并查集,或set)

题目链接

题目大意

一些骑士打架,输了就淘汰,输出一个数组,表示第i个人是被a[i]淘汰的。
因为涉及到区间的修改,不可避免的想到了线段树,可惜菜鸡只会用区间加的板子,这种值替换的线段树不会写,菜哭了。
还是一手正难则反,考虑倒着处理每一次战斗,这样可以覆盖之前的的修改。

代码

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

你可能感兴趣的:(codeforces)