用堆实现的贪心——注重思想吧

Posted 世界光明

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用堆实现的贪心——注重思想吧相关的知识,希望对你有一定的参考价值。

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

In the first line of the standard input there are three integers: nnn,kkk,ppp (1≤k≤n≤100 0001\le k\le n\le 100\ 0001kn100 000, 1≤p≤500 0001\le p\le 500\ 0001p500 000), separated by single spaces. These denote respectively: the total number of cars, the number of cars that can remain on the floor at once and the length of the sequence of cars which Johnny will want to play with. Each of the following ppp lines contains one integer. These integers are the numbers of cars Johnny will want to play with (the cars are numbered from 111 to nnn).

 

In the first and only line of the standard output one integer should be written - the minimal number of times his mother has to pick a car from the shelf.

 

输入 #1

3 2 7
1
2
3
1
3
1
2

输出 #1
4

#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<iostream>
using namespace std;
const int maxn=6e5+10;
struct node
{
    int num,nxt;
    bool operator <(const node &x ) const
    {
        return nxt<x.nxt;//下一次出现的时间 
    }
};
priority_queue<node> q;
int t,n,k,p,a[maxn],head[maxn],nxt[maxn],chosen[maxn],ans;

int main()
{
    //scanf("%d",&t);
    //while(t--)
    //{
        ans=0;
        memset(head,0,sizeof(head));
        memset(nxt,0,sizeof(nxt));
        memset(chosen,0,sizeof(chosen));
        while(q.size()) q.pop();
        scanf("%d%d%d",&n,&k,&p);
        for(int i=1;i<=p;i++)
        {
            scanf("%d",a+i);
        }
        for(int i=p;i>=1;i--)
        {
            if(head[a[i]]) nxt[i]=head[a[i]];//记录当前位置的下一次出现的位置 
            head[a[i]]=i;
        }
        for(int i=1;i<=p;i++) if(!nxt[i]) nxt[i]=p+1;//没有下一次的位置赋值 
        for(int i=1;i<=p;i++)
        {
            if(chosen[a[i]])//选过 
            {
                q.push((node){a[i],nxt[i]});//将下一次出现的丢进去 
                continue;
            }
            if(k)//还有位置 
            {
                q.push((node){a[i],nxt[i]});
                chosen[a[i]]=1;
                k--;ans++;
            }
            else//位置满了,要找到一个下一次最晚出现的拿上去, 
            {
                while(!chosen[q.top().num]&&q.size()) q.pop();//找到第一个选过的 
                chosen[q.top().num]=0;
            //    cout<<q.top().num<<endl;
                if(q.size())q.pop();
                q.push((node){a[i],nxt[i]});
                chosen[a[i]]=1;
                ans++;
            }
        }
        printf("%d\n",ans);
    //}
    return 0;
}

要次数少嘛,所以玩的越久越好,要知道我们要把哪一个拿上去,不能频繁的拿上拿下,所以我们要比较下一次出现的位置,下一次出现的越晚,我们就可以把这个拿上去,这就是这道题的贪心思想。

以上是关于用堆实现的贪心——注重思想吧的主要内容,如果未能解决你的问题,请参考以下文章

面向对象思想

优先级队列总结

Lambda表达式——注重过程的编程思想

E - New Game Plus! 堆贪心 思维

题解 P2949 [USACO09OPEN]工作调度Work Scheduling

常见算法——贪心算法&分治算法