[STL] Codeforces 69E Subsegments

Subsegments
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Programmer Sasha has recently begun to study data structures. His coach Stas told him to solve the problem of finding a minimum on the segment of the array in , which Sasha coped with. For Sasha not to think that he had learned all, Stas gave him a new task. For each segment of the fixed length Sasha must find the maximum element of those that occur on the given segment exactly once. Help Sasha solve this problem.

Input

The first line contains two positive integers n and k (1 ≤ n ≤ 105, 1 ≤ k ≤ n) — the number of array elements and the length of the segment.

Then follow n lines: the i-th one contains a single number ai ( - 109 ≤ ai ≤ 109).

Output

Print nk + 1 numbers, one per line: on the i-th line print of the maximum number of those numbers from the subarray ai ai + 1 … ai + k - 1that occur in this subarray exactly 1 time. If there are no such numbers in this subarray, print "Nothing".

Examples
input
Copy
5 3
1
2
2
3
3
output
Copy
1
3
2
input
Copy
6 4
3
3
3
4
4
2
output
s
Copy
4
Nothing
3

题意:给一个长度为n的数字,输出i从1到n-k-1,i到i+k-1这个区间内若存在只出现一次的区间最大值则输出这个值,否则输出Nothing

思路:先把前k个数排序并找出只出现一次的那些数,就可以的到第一次询问的答案,
然后从k+1开始,每加入一个数就删去上一个区间的第一个数,并看删去的那个数的个数
是否为1,若为1则加入可行集合,否则就看它是否在可行集合中(因为刚才删了一次,若它在可行集合中那么它的数量就为0了,要把它给删了)
若在就删了它。再看新加进来的那个数的个数是否为1,如果是就加入可行集合,否则就看它是否在可行集合中(如果它在可行集合中,那么它现在的数量为1,现在又加了一次它,它的个数就大于1,不符合条件了),若在就把它给删了
每次输出可行集合中最大的那个数

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int amn=1e5+5;
 4 int a[amn];
 5 map<int,int> mp;    ///个数统计,a[i]最大是1e9,故用map统计
 6 set<int> s; ///可行集合
 7 int main(){
 8     int n,k;
 9     ios::sync_with_stdio(0);
10     cin>>n>>k;
11     for(int i=1;i<=n;i++){
12         cin>>a[i];
13         if(i<=k){
14             mp[a[i]]++;
15             if(mp[a[i]]==1){
16                 s.insert(a[i]);
17             }
18             else{
19                 if(s.find(a[i])!=s.end()){
20                     s.erase(a[i]);
21                 }
22             }
23             if(i==k){
24                 if(s.empty())printf("Nothing
");
25                 else{
26                     printf("%d
",*(--s.end()));    ///set升序排序,输出最后一个
27                 }
28             }
29         }
30         else{
31             mp[a[i]]++;
32             mp[a[i-k]]--;
33             if(mp[a[i-k]]==1)s.insert(a[i-k]);
34             else{                               ///可能为0了,如果这个数在可行集合中就要把它删掉
35                 if(s.find(a[i-k])!=s.end()){
36                     s.erase(a[i-k]);
37                 }
38             }
39             if(mp[a[i]]==1)s.insert(a[i]);
40             else{
41                 if(s.find(a[i])!=s.end()){
42                     s.erase(a[i]);
43                 }
44             }
45             if(s.empty())printf("Nothing
");
46             else{
47                  printf("%d
",*(--s.end()));
48             }
49         }
50     }
51 }
52 /***
53 先把前k个数排序并找出只出现一次的那些数,就可以的到第一次询问的答案,
54 然后从k+1开始,每加入一个数就删去上一个区间的第一个数,并看删去的那个数的个数
55 是否为1,若为1则加入可行集合,否则就看它是否在可行集合中(因为刚才删了一次,若它在可行集合中那么它的数量就为0了,要把它给删了)
56 若在就删了它。再看新加进来的那个数的个数是否为1,如果是就加入可行集合,否则就看它是否在可行集合中(如果它在可行集合中,那么它现在的数量为1,现在又加了一次它,它的个数就大于1,不符合条件了),若在就把它给删了
57 每次输出可行集合中最大的那个数
58 ***/
原文地址:https://www.cnblogs.com/Railgun000/p/11291012.html