NYOJ 华山论剑

华山论剑

时间限制: 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 2
1 2 2
1 3 2
样例输出
2 0 2

        这个题目当时一看有查询,就想到了线段树的做法,做完之后看了看标程,发现别人是使用状态压缩做的,这里给大家介绍一下用线段树怎样做的,不用建树,不用查询操作,只涉及到区间更新,基础的知识。
#include <iostream>
#include <cstdio>
#include <cstring>
#define lson l,mid,d<<1
#define rson mid+1,r,d<<1|1
using 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值