1. 程式人生 > >2018 Multi-University Training Contest 1 Distinct Values 【貪心 + set】

2018 Multi-University Training Contest 1 Distinct Values 【貪心 + set】

std c++ nts put names ica 刪除 個數 meet

任意門:http://acm.hdu.edu.cn/showproblem.php?pid=6301

Distinct Values

Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5312 Accepted Submission(s): 1823


Problem Description Chiaki has an array of n positive integers. You are told some facts about the array: for every two elements ai
and aj in the subarray al..r (li<jr), aiajholds.
Chiaki would like to find a lexicographically minimal array which meets the facts.

Input There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:

The first line contains two integers n
and m (1n,m105) -- the length of the array and the number of facts. Each of the next m lines contains two integers li and ri (1lirin).

It is guaranteed that neither the sum of all n nor the sum of all m exceeds 106.

Output For each test case, output n integers denoting the lexicographically minimal array. Integers should be separated by a single space, and no extra spaces are allowed at the end of lines.

Sample Input 3 2 1 1 2 4 2 1 2 3 4 5 2 1 3 2 4

Sample Output 1 2 1 2 1 2 1 2 3 1 1

Source 2018 Multi-University Training Contest 1

題意概括:

需要求一個長度為 N 的序列,要求滿足給出的 M 的子區間內不能出現重復的數,要求字典序最小。

解題思路:

一開始直接雙指針模擬,但是果斷WA,原因就是當前子區間不能的數不一定是連續的,需要記錄前面不能使用的數。

後來用了一個標記數組記錄所有不能用的數,TL,想想也知道,查詢和維護需要時間復雜度太高。

那有什麽可以快速維護這些當前可以使用的數,並且把已經使用過的數刪除掉的呢?

C++ STL 裏 的 set (可以說功能十分強大了,自動升序排序,可查詢,刪除)

那麽如果知道了當前區間不能時候用什麽數,能使用什麽數,剩下的就是貪心策略了,盡可能地把需要滿足條件子區間擴大(大的子區間滿足了它所包含的小的子區間肯定也是滿足的)。

用一個數組記錄當前序列位置 x 所在的區間的最左值即可。

根據這個最左值 pre[x] 就可以判斷當前以求的答案序列裏 < pre[x] 的數都是可以用來填充當前子區間的。

AC code:

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<cstring>
 5 #include<vector>
 6 #include<queue>
 7 #include<cmath>
 8 #include<set>
 9 #define INF 0x3f3f3f3f
10 #define LL long long
11 using namespace std;
12 const int MAXN = 1e5+10;
13 int num[MAXN];
14 int pre[MAXN];
15 int ans[MAXN];
16 set<int>ss;
17 int N, M;
18 int main()
19 {
20     int l, r;
21     int T_case;
22     scanf("%d", &T_case);
23     while(T_case--){
24         ss.clear();
25         scanf("%d %d", &N, &M);                                            //初始化
26         for(int i = 1; i <= N; i++){pre[i] = i; ss.insert(i);}
27         for(int i = 1; i <= M; i++){scanf("%d %d", &l, &r); pre[r] = min(pre[r], l);}
28         for(int i = N-1; i >= 1; i--) pre[i] = min(pre[i], pre[i+1]);
29         int p = 1;
30         for(int i = 1; i <= N; i++){
31             while(p < pre[i]){ss.insert(ans[p]);p++;}
32             ans[i] = *ss.begin();
33             ss.erase(ans[i]);
34         }
35 
36         for(int i = 1; i <= N; i++){printf("%d", ans[i]);if(i < N) printf(" ");}
37         puts("");
38     }
39     return 0;
40 }

2018 Multi-University Training Contest 1 Distinct Values 【貪心 + set】