Knight Tournament

Codeforces Round #207 (Div. 1) A:http://codeforces.com/problemset/problem/356/A

题意:给你n匹马,然后有m场比赛。每场比赛有一个l,r,x,表示编号从l,r之间的马都被x给打败了,但是这里如果之前已经败了,那么这里的区间就不会包括了。

题解:题解,直接用一个set搞定。

思维过程:首先,想到,对于一场比赛来说,如果之前已经败了的话,这里就不用在考虑了,但是如何判断这个区间里面的马已经败了,朴素的想法,就是查询还是在这个区间,但是我把之前的已经败的马打上表示,然后再在这个区间内逐个进行判断,这样判断的话,区间内的每个元素都会被判断一次,可想而知,这样的想法是不对。时间复杂度hold不住。如何对于那些已经败的马不用判断。这里,可以用一个set来搞,把所有的元素放进set,当要删除一个区间的时候,只要用lower_bound找到第一个不小于l的数,然后往后找,直到到达右端点。然后把找到的点,从set中删除即可。这样,每次查询只在没有删除的马中进行,所以减少了许多不必要的判断。现在考虑复杂度。每个数,会被放进set和从set中删除一次,所以复杂度是n(logn).一定要利用题目中的各种信息,然后利用好自己的思维信息,寻找突破口,一点一滴的,总会有解决的方法。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<set>
 6 using namespace std;
 7 const int N=3e5+10;
 8 int ans[N],temp[N],top;
 9 int n,m,l,r,x;
10 int main(){
11    while(~scanf("%d%d",&n,&m)){
12       set<int>Q;
13       for(int i=1;i<=n;i++){
14         Q.insert(i);
15       }
16       for(int i=1;i<=m;i++){
17         scanf("%d%d%d",&l,&r,&x);
18           top=0;
19         set<int>::iterator it=Q.lower_bound(l);
20         for(;it!=Q.end();it++){
21             if((*it)>r)break;
22             if((*it)==x){
23                 ans[x]=x;
24             }
25             else{
26                 ans[(*it)]=x;
27                 temp[++top]=(*it);
28             }
29         }
30         for(int i=1;i<=top;i++){
31             Q.erase(temp[i]);
32         }
33         top=0;
34       }
35     for(int i=1;i<n;i++){
36         if(ans[i]==i)printf("0 ");
37         else
38             printf("%d ",ans[i]);
39     }
40     if(ans[n]==n)printf("0
");
41     else
42         printf("%d
",ans[n]);
43    }
44 
45 
46 
47 }
View Code
原文地址:https://www.cnblogs.com/chujian123/p/3895808.html