Template Library Management
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1113 Accepted Submission(s): 305
Problem Description
As an experienced ACMer, you must have known the importance of "code template library". With the help of pre-printed code library, you can implement the complicated algorithms correctly and efficiently. However, the size of the library is strictly limited during the contest. For example, you can only take at most 25 pages of printed codes in World Finals. So you must choose carefully which code template should be included.
Now your team is participating a programming contest whose rules are slightly different from ICPC. This contest consists of N problems, and you must solved them in order: Before you solve the (i+1)th problem, you must solve the ith problem at first. And solving the ith problem requires a specified code template Ti.
You are allowed to hold M code templates only. At the beginning of the contest, your are holding templates numbered 1, 2, ..., M. During the contest, if the problem you are trying to solve requires code template Ti, and Ti is happened at your hand (i.e, one of the M code templates you are holding is Ti), you can solve it immediately. On the other hand, if you are not holding Ti, you must call your friends who are outside the arena for help (yes, it is permitted, not cheating). They can give you the code template you need. Because you are only allowed to hold M code templates, after solving current problem, you must choose to drop the code you get from your friends just now, or to keep it and drop one of the M templates at your hand previously.
Given the problem sequence in the contest and the limitation M, you want finish all the problems with minimum number of calling your friends.
Input
The first line of each test case contains two numbers N (1 <= N <= 100000) and M (1 <= M <= 100000). The second line contains N numbers T1, T2, ..., TN (1 <= Ti<= 109), indicating the code templates required by each problem.
Output
Output one line for each test case, indicating the minimum number of calling friends for help.
![](/qrcode.jpg)
Sample Input
4 3 1 2 3 4 11 3 4 1 2 1 5 3 4 4 1 2 3
Sample Output
1 4
题意:
你有n道题(每道题都有一个编号a[i](a[i]<=1e9),n<=1e5),你只有编号为1~m(m<=1e5)的的答案,每次你没有对应编号答案的时候你可以求助一个编号答案,并自己决定留下这个编号的答案并扔掉手里的另一个编号的答案,还是丢弃这个答案。求最少运用多少次求助可以解决所有的题目。
思路:
这就是理想情况下的最优调度算法了吧。。。因为可以预知将来要用那些编号的答案。。。
预处理每一个编号出现的下一个位置。将刚开始手里有的编号加入到优先队列中,按这个编号第一次出现的位置排序(没出现就是n+1),大的在队头。
每次需要换的时候找队头,再根据当前编号的下一个位置还是队头编号的下一个位置大小考虑留哪个。
代码:
#include<iostream>
#include<cmath>
#include<iomanip>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<string>
#include<queue>
#include<vector>
#include<map>
#define ll long long
#define inf 0x3f3f3f3f
#define rep(i,a,b) for(register int i=(a);i<=(b);++i)
using namespace std;
const int maxn=200010;
int n,m;
map<int,int>pre,pos,in;
int a[maxn],nxt[maxn];
int main()
{
int T,cas=1;
while(scanf("%d%d",&n,&m)!=EOF)
{
pos.clear();pre.clear();
in.clear();
rep(i,1,n)
{
scanf("%d",&a[i]);
if(!pre[a[i]])
pre[a[i]]=i;
if(pos[a[i]])
nxt[pos[a[i]]]=i;
pos[a[i]]=i;
nxt[i]=n+1;
}
//rep(i,1,n)
//cout<<nxt[i]<<" ";
priority_queue<pair<int,int> >q;
rep(i,1,m)
{
in[i]=1;
if(!pre[i])
q.push(make_pair(n+1,i));
else q.push(make_pair(pre[i],i));
}
/*
while(!q.empty())
{
pair<int,int>x=q.top();
q.pop();
cout<<x.first<<" "<<x.second<<endl;
}
*/
int sum=0;
rep(i,1,n)
{
if(in[a[i]])
{
q.push(make_pair(nxt[i],a[i]));
continue;
}
while(1)
{
pair<int,int>x=q.top();
q.pop();
if(!in[x.second]) continue;
if(x.first>nxt[i]){
in[x.second]=0;
in[a[i]]=1;
//cout<<x.second<<"->"<<a[i]<<endl;
q.push(make_pair(nxt[i],a[i]));
}
else q.push(x);
sum++;
break;
}
}
printf("%d\n",sum);
}
return 0;
}