CSU 1554 SG Value (multiset/priority queue 思维题)
题目链接:http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1554
Description
The SG value of a set (multiset) is the minimum positive integer that could not be constituted of the number in this set.
You will be start with an empty set, now there are two opertions:
1. insert a number x into the set;
2. query the SG value of current set.
Input
Input contains multiple test cases. Each test case starts with a number N (0 < N <= 1e5) -- the total number of opertions.
The next N lines contain one opertion each.
1 x means insert a namber x into the set;
2 means query the SG value of current set.
Output
For each query output the SG value of current set.
Sample Input
5 2 1 1 2 1 1 2
Sample Output
1 2 3
Hint
Source
题意:
SG Value 是在这个集合里任意组合,不能组合成的最小的数。例:{1, 2}可以组成[1,3]的数,所以SG Value 是4。
有两个操作。
1)添加一个数进入集合
2)找到当前集合中的SG Value。
题解:
给你一个区间[L, R], 那么我们的sg value 就是 R+1。
一开始我们的集合是[0,0], sg value 是 1。如果我们加入2,sg value 还是1。所以我们要加入的数要小于等于 sg value 区间范围才会改变。我们就需要排个序,从小到到找。
而这题加入了一个添加操作,只需要用优先队列或者 multiset 来维护。
{1, 2, 5},前两个来说可以组成[1,3], 就可以把他们删除掉。
优先队列
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <string> 6 #include <vector> 7 #include <map> 8 #include <set> 9 #include <queue> 10 #include <sstream> 11 #include <algorithm> 12 using namespace std; 13 #define pb push_back 14 #define mp make_pair 15 #define ms(a, b) memset((a), (b), sizeof(a)) 16 //#define LOCAL 17 #define eps 0.0000001 18 typedef long long LL; 19 const int inf = 0x3f3f3f3f; 20 const int maxn = 500+10; 21 const int mod = 1000000007; 22 int n; 23 void solve() 24 { 25 priority_queue<LL, vector<LL>, greater<LL> >q; 26 LL R = 0; 27 for(int i=0;i<n;i++){ 28 int x; 29 scanf("%d", &x); 30 if(x==2){ 31 while(!q.empty() && q.top() <= R+1LL){ 32 R= R+q.top(); 33 q.pop(); 34 } 35 printf("%lld\n", R+1LL); 36 } 37 else{ 38 int v; 39 scanf("%lld", &v); 40 q.push(v); 41 } 42 } 43 } 44 int main() 45 { 46 #ifdef LOCAL 47 freopen("jumping.in", "r", stdin); 48 // freopen("output.txt", "w", stdout); 49 #endif // LOCAL 50 while(~scanf("%d", &n)){ 51 solve(); 52 } 53 return 0; 54 }
multiset
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <string> 6 #include <vector> 7 #include <map> 8 #include <set> 9 #include <queue> 10 #include <sstream> 11 #include <algorithm> 12 using namespace std; 13 #define pb push_back 14 #define mp make_pair 15 #define ms(a, b) memset((a), (b), sizeof(a)) 16 //#define LOCAL 17 #define eps 0.0000001 18 typedef long long LL; 19 const int inf = 0x3f3f3f3f; 20 const int maxn = 500+10; 21 const int mod = 1000000007; 22 int n; 23 void solve() 24 { 25 multiset <LL> q; 26 LL R = 0; 27 for(int i=0;i<n;i++){ 28 int x; 29 scanf("%d", &x); 30 if(x==2){ 31 while(!q.empty() && *q.begin() <= R+1LL){ 32 R= R+ *q.begin(); 33 q.erase(q.begin()); 34 } 35 printf("%lld\n", R+1LL); 36 } 37 else{ 38 LL v; 39 scanf("%lld", &v); 40 q.insert(v); 41 } 42 } 43 } 44 int main() 45 { 46 #ifdef LOCAL 47 freopen("jumping.in", "r", stdin); 48 // freopen("output.txt", "w", stdout); 49 #endif // LOCAL 50 while(~scanf("%d", &n)){ 51 solve(); 52 } 53 return 0; 54 }
总结:
学到了一个multiset。是一个可以出现重复key的set。而且它的第一个数是最小值。(通过红黑二叉树实现的)
你努力的时候,比你厉害的人也在努力