NYOJ 华山论剑

来源:互联网 发布:手机识图软件 编辑:程序博客网 时间:2024/05/17 01:35

华山论剑

时间限制:1000 ms  |  内存限制:65535 KB
难度:3
描述

有n个剑客(编号1~n)相约华山比剑,分 m 次决斗,为了节省时间,每次决斗 编号在[l,r]的剑客一起决斗,然后xi获胜。当进行下一次决斗,失败后的剑客可能再参与到决斗,m 次决斗后可能不止一位获胜者(没有失败过就视为获胜者)。

输入
多组测试数据。
对于每组测试数据,第一行输入n和m。接下来输入m行,每行输入l,r,xi。
2 ≤ n ≤ 3*10^5; 1 ≤ m ≤ 3*10^5,l ≤ xi ≤ r
输出
每组测试数据输出n个数字,数字间用空格隔开。第i个数子表示第一次击败i号剑客的剑客编号,若i号剑客是最后的获胜者,输出0;
样例输入
3 21 2 21 3 2
样例输出
2 0 2

       这个题目当时一看有查询,就想到了线段树的做法,做完之后看了看标程,发现别人是使用状态压缩做的,这里给大家介绍一下用线段树怎样做的,不用建树,不用查询操作,只涉及到区间更新,基础的知识。
#include <iostream>#include <cstdio>#include <cstring>#define lson l,mid,d<<1#define rson mid+1,r,d<<1|1using namespace std;int t[301000*5],a[301000];//a数组记录获胜者//t数组用来标记该区间内还是否有没有胜利的人//没有失败的人用1标记,单点更新int n,m,u,v,w;void up(int l,int r,int d,int ll,int rr){  if(t[d])return;//如果区间l~r的人都胜利了,就返回  if(l==r){    if(t[d]==0&&l!=w&&l==ll){//如果未曾获胜并且此人非胜利者        t[d] = 1;//标记该点        a[l] = w;//记录第一次打败l的人w    }    return;  }  int mid = (l+r)>>1;  if(rr<=mid)up(lson,ll,rr);  else if(ll>mid)up(rson,ll,rr);  else {    up(lson,ll,mid);    up(rson,mid+1,rr);  }  t[d]=t[d<<1]&&t[d<<1|1];//采用与操作向上更新 }int main(){    while(~scanf("%d%d",&n,&m)){        memset(t,0,sizeof(t));        memset(a,0,sizeof(a));        while(m--){            scanf("%d%d%d",&u,&v,&w);            up(1,n,1,u,v);        }        for(int i = 1;i <= n;i++){            printf("%d ",a[i]);        }        printf("\n");    }    return 0;}
1 0
原创粉丝点击