题意:n道题,每道题需要一个模板,现在手头有m个模板(标号1~m),解题的时候,如果没有需要的模板,可以向朋友借,但是用完之后必须在还给朋友一个模板(也就是说保持手头拥有m个模板),求解完n道题最少需要向朋友请求多少次帮助。
思路:贪心,每次抛弃模板的时候抛弃下次使用最靠后的那一个。(怎么想到的。。怎么证明。)
#include<iostream> #include<stdio.h> #include<map> #include<set> using namespace std; const int MAXN=100005; int Ti[MAXN];//模板标号 int _next[MAXN];//下个模板位置 map<int,int>mp;//模板出现位置 struct Node{ int next_id;//下个模板位置 int ti;//当前标号 }; struct classCompare{ bool operator()(const Node &a,const Node &b)const{ return a.next_id<b.next_id;//升序 } }; multiset<Node,classCompare>T_info;//模板信息 multiset<Node>::iterator it_n; set<int>Te;//模板标号 set<int>::iterator it; int main(){ int n,m,i,ans; Node temp; while(~scanf("%d%d",&n,&m)){ for(i=1;i<=n;++i)scanf("%d",&Ti[i]); mp.clear();//清空map for(i=n;i>=1;--i){//从后往前扫描 if(mp[Ti[i]])//出现过 _next[i]=mp[Ti[i]]; else _next[i]=n+1; mp[Ti[i]]=i; } Te.clear(); T_info.clear(); for(i=1;i<=m;++i){//把带的m个模板加入set if(!mp[i])mp[i]=n+1; temp.next_id=mp[i]; temp.ti=i; Te.insert(i); T_info.insert(temp); } ans=0; for(i=1;i<=n;++i){//遍历每道题需要的模板 it=Te.find(Ti[i]); if(it!=Te.end()){ temp.next_id=i; temp.ti=Ti[i]; T_info.erase(temp); temp.next_id=_next[i];//更新 T_info.insert(temp); } else{ ++ans; it_n=T_info.end();// --it_n;//最靠后的一个 if(_next[i]<(*it_n).next_id){ Te.erase((*it_n).ti); T_info.erase(it_n); Te.insert(Ti[i]); temp.next_id=_next[i]; temp.ti=Ti[i]; T_info.insert(temp); } } } printf("%d ",ans); } return 0; }