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


    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 0001le kle nle 100 0001kn100 000, 1≤p≤500 0001le ple 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
    ",ans);
        //}
        return 0;
    }

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

  • 相关阅读:
    异常
    一线互联网大厂,内推吧!
    node-sass 安装失败的解决办法
    上下文执行栈
    1像素边框
    babel需要这样配置
    【webpack】中enforce的使用方法
    【webpack】中resolveLoader的使用方法
    【webpack】中的devtool的使用方法
    【webpack】中splitChunk的使用方法
  • 原文地址:https://www.cnblogs.com/WHFF521/p/11241443.html
Copyright © 2020-2023  润新知