[bzoj1528/POI2005]sam-Toy Cars---贪心+堆

来源:互联网 发布:怎样成为数据分析师 编辑:程序博客网 时间:2024/06/16 11:55

Description

Jasio 是一个三岁的小男孩,他最喜欢玩玩具了,他有n 个不同的玩具,它们都被放在了很高的架子上所以Jasio 拿不到它们. 为了让他的房间有足够的空间,在任何时刻地板上都不会有超过k 个玩具. Jasio 在地板上玩玩具. Jasio’的妈妈则在房间里陪他的儿子. 当Jasio 想玩地板上的其他玩具时,他会自己去拿,如果他想玩的玩具在架子上,他的妈妈则会帮他去拿,当她拿玩具的时候,顺便也会将一个地板上的玩具放上架子使得地板上有足够的空间. 他的妈妈很清楚自己的孩子所以他能够预料到Jasio 想玩些什么玩具. 所以她想尽量的使自己去架子上拿玩具的次数尽量的少,应该怎么安排放玩具的顺序呢?
Input

第一行三个整数: n, k, p (1 <= k <= n <= 100.000, 1 <= p <= 500.000), 分别表示玩具的总数,地板上玩具的最多个数以及Jasio 他想玩玩具的序列的个数,接下来p行每行描述一个玩具编号表示Jasio 想玩的玩具.
Output

一个数表示Jasio 的妈妈最少要拿多少次玩具.
Sample Input

3 2 7
1
2
3
1
3
1
2
Sample Output

4

分析

看似无从下手,实际上就是贪心:
第k天后,当要去上面拿玩具时,顺便带走下一次位置最远的(后者以后用不到的)即可。至于实现,用堆维护吧

代码

#include <cstdio>#include <cstdlib>#include <queue>#define open(s) freopen(s".in","r",stdin); freopen(s".out","w",stdout);#define close fclose(stdin); fclose(stdout);using namespace std;struct node{    int p;//玩具编号    int w;//下一次的位置    bool operator < (const node &b) const    {        return w<b.w;//大根堆    }};int a[5000005];int next[1000005];//下一次位置int head[1000005];//辅助记录(可无视)bool floor[1000005];//是否需要拿(在地板上)int n,k,p;inline int read(){    int k=1;    int sum=0;    char c=getchar();    for(;'0'>c || c>'9' ;c=getchar())        if(c=='-') k=-1;    for(;'0'<=c && c<='9';c=getchar())        sum=sum*10+c-'0';    return sum*k;}inline void write(int x){    if(x<0) { putchar('-'); x*=-1; }    if(x>9) write(x/10);    putchar(x%10+'0');}int main(){    open("sam");    n=read(); k=read(); p=read();    for(int i=1;i<=p;++i)    {        a[i]=read();        if(head[a[i]]) next[head[a[i]]]=i;        head[a[i]]=i;//类似前向星    }    for(int i=1;i<=p;++i)    if(!next[i]) next[i]=p+1;//最后一个的下一个赋值    int ans=0;    priority_queue<node>q;    for(int i=1;i<=p;++i)    {        if(floor[a[i]]) { q.push((node){a[i],next[i]}); continue ;  }//如果在地板上的话,入堆直接跳过        if(k)//如果没有超限,直接拿        {            q.push((node){a[i],next[i]});            floor[a[i]]=1;            --k; ++ans;        }else        {            for(;!floor[q.top().p];) q.pop();//不在地板上,跳过            floor[q.top().p]=0;//带走一个            q.pop();            q.push((node){a[i],next[i]});//加入一个            floor[a[i]]=1;            ++ans;        }    }    write(ans);    close;    return 0;}
原创粉丝点击