华山论剑
时间限制:
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
华山论剑
时间限制:
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;
}