bzoj 1826 缓存交换
题目大意:
一些数,需要将他们依次取入一个集合中
集合的容量有限
若该数已经在集合中则不用再取
每次取的时候可以将集合中与元素替换为另一个,也可以不换,直接加入前提是不超过集合容量
求最后最小的取数次数
思路:
可以想到一个贪心算法
就是下一次将要被取位置越远的书应该先被从集合中删除
因此我们可以使用优先队列这一STL来表示当前集合
当集合未满的时候不停的推入直到集合满
集合满的时候若元素不在集合中,则删除下一个位置最远的队首,然后加入
但是当元素在集合时,我们不能不予处理,需要更新它的下一次位置
但是这样非常难做,就需要我们把容量++,把这个新的元素加入队列
还要离散化。。
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstring> 6 #include<cstdlib> 7 #include<queue> 8 #include<vector> 9 #include<map> 10 #include<stack> 11 #define inf 2147483611 12 #define ll long long 13 #define MAXN 101010 14 using namespace std; 15 inline int read() 16 { 17 int x=0,f=1; 18 char ch;ch=getchar(); 19 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 20 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 21 return x*f; 22 } 23 struct pr 24 { 25 int next,val; 26 bool operator < (const pr &a) const 27 { 28 return next<a.next; 29 } 30 }a[MAXN]; 31 struct data 32 { 33 int pos,val; 34 }g[MAXN]; 35 bool cmp(data p,data q) {return p.val<q.val;} 36 int n,k,hash[MAXN],ans; 37 priority_queue <pr> q; 38 bool vis[MAXN]; 39 int main() 40 { 41 n=read(),k=read(); 42 for(int i=1;i<=n;i++) g[i].val=read(),g[i].pos=i; 43 sort(g+1,g+n+1,cmp); 44 int cnt=1; 45 for(int i=1;i<=n;i++) 46 { 47 a[g[i].pos].val=cnt;if(g[i].val!=g[i+1].val) cnt++; 48 } 49 for(int i=1;i<=n;i++) hash[a[i].val]=i; 50 for(int i=n;i>=1;i--) 51 { 52 if(hash[a[i].val]!=i) a[i].next=hash[a[i].val]; 53 else a[i].next=inf; 54 hash[a[i].val]=i; 55 } 56 int i=1; 57 while(ans<k&&i<=n) 58 { 59 if(!vis[a[i].val]) ans++; 60 q.push(a[i]); 61 vis[a[i].val]=1; 62 i++; 63 } 64 for(i;i<=n;i++) 65 { 66 if(vis[a[i].val]) {q.push(a[i]);continue;} 67 vis[q.top().val]=0; 68 vis[a[i].val]=1; 69 q.pop(); 70 q.push(a[i]); 71 ans++; 72 } 73 printf("%d",ans); 74 }