http://codeforces.com/problemset/problem/356/A
首先理解题意
每次给出l 和r 在l - r之间还有资格的选手中得出一个胜者
暴力思路:
首先维护还有资格的选手的集合
用一个数组 表示 这个选手被谁击败
每次遍历 l - r 然后把不是胜者 且 还在集合中的选手踢出 并更新这个选手的数组值
最终 输出这个数组即可
这样会TLE
1、 如果用数组维护这个集合的话 每次遍历都是这样就是O(n^2) -->> 所以用set维护这个集合
2、使用set后 如果每次依然从l - r去遍历找在集合中的元素 去find的话 那么就会在 (l, r)的区间两端有浪费的运算 如果每次l, r 都是1 和 n的话 那就浪费得非常得多
所以使用set :: lower_bound() 直接得到第一个大于l 并在集合中的元素 O(logn)
这样优化后 即可
1 #include <iostream> 2 #include <stdio.h> 3 #include <set> 4 using namespace std; 5 6 7 int Par[300007]; 8 int tmp[300007]; 9 set<int> s; 10 11 int find(int x) 12 { 13 if (Par[x] == x) return x; 14 else return find(Par[x]); 15 } 16 17 int main() 18 { 19 int n, m; 20 freopen("in.txt", "r", stdin); 21 scanf("%d%d", &n, &m); 22 for (int i = 0; i <= n; i++) 23 { 24 Par[i] = i; 25 s.insert(i);//加入set中 26 } 27 for(int i = 0; i < m; i++) 28 { 29 int l, r, x; 30 scanf("%d%d%d", &l, &r, &x); 31 set<int> :: iterator pit = s.lower_bound(l);//返回第一个>= l的位置 32 int num = 0; 33 while (pit != s.end() && (*pit) <= r ) 34 { 35 if ((*pit) != x) 36 { 37 Par[*pit] = x; 38 //s.erase(*pit); 不能在这里直接删除 删除后set结构发生改变 pit就失效了 39 tmp[num++] = *pit; 40 } 41 pit++; 42 } 43 for (int j = 0; j < num; j++) s.erase(tmp[j]); 44 } 45 for (int i = 1; i <= n; i++) 46 { 47 if (Par[i] == i) printf("0 "); 48 else printf("%d ", Par[i]); 49 } 50 putchar(‘\n‘); 51 }
时间: 2024-10-09 23:26:34