zoukankan      html  css  js  c++  java
  • 【贪心】codeforces B. Heidi and Library (medium)

    http://codeforces.com/contest/802/problem/B

    【题意】

    有一个图书馆,刚开始没有书,最多可容纳k本书;有n天,每天会有人借一本书,当天归还;如果图书馆有这个本就直接借到,否则图书馆的人会购买这本书,每本书的价格都是1;如果现在图书馆的书已达上限还需购买,必须舍弃已有的一本书,以后再有人借这本书要重新购买。

    问图书馆的人最少要花多少钱购书?

    数据范围变成了4000 00.

    【思路】

    关键是替换原则,每次都替换下一次出现最晚的,因为它占用图书馆的时间最长。

    【官方题解】

    Here we need to be much more ecient. There are many data structures that one can use. One idea is to
    store a queue of remaining requests for each possible book (initializing it at the beginning and removing
    requests from the front as they arrive) and an std::set-like structure (based on a balanced binary search
    tree; it is also possible to use a priority queue based on a heap) which stores books that are currently at the
    library, sorted by their next-request time.

    这里我用优先级队列找出每次应该替换哪一个,用队列记录每个图书馆中的元素出现位置的情况,不断更新pq和q。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<string>
      5 #include<cmath>
      6 #include<vector>
      7 #include<algorithm>
      8 #include<queue>
      9 #include<map>
     10 using namespace std;
     11 typedef long long ll;
     12 const int maxn=4e5+5;
     13 int a[maxn];
     14 int b[maxn];
     15 map<int,int> mp;
     16 struct Node
     17 {
     18     int id;
     19     int num;
     20     Node(int iid,int nnum):id(iid),num(nnum){}
     21 };
     22 //根据id排序,优先级队列先pop的是排在后面的,也就是下一次出现最晚的 
     23 bool operator<(Node a,Node b)
     24 {
     25     return a.id<b.id;
     26 }
     27 //每个数都有一个出现位置的队列 
     28 queue<int> q[maxn];
     29 priority_queue<Node> pq;
     30 int vis[maxn];
     31 int n,m;
     32 int main()
     33 {
     34     while(~scanf("%d%d",&n,&m))
     35     {
     36         memset(vis,0,sizeof(vis));
     37         for(int i=1;i<=n;i++)
     38         {
     39             scanf("%d",&a[i]);
     40         } 
     41         int ans=0;
     42         int cnt=0;
     43         int i;
     44         for(i=1;i<=n;i++)
     45         {
     46             if(cnt<m)
     47             {
     48                 if(!vis[a[i]])
     49                 {
     50                     b[++cnt]=a[i];
     51                     vis[a[i]]=1;
     52                     ans++;
     53                 }
     54             }
     55             else
     56             {
     57                 break;
     58             }
     59         }
     60         if(cnt<m)
     61         {
     62             printf("%d
    ",ans);
     63             continue;
     64         }
     65         //q[a[k]] 为a[k]从小到大出现位置的队列 ,要从i开始算,以前的都不用记 
     66         for(int k=i;k<=n;k++)
     67         {
     68             q[a[k]].push(k);
     69         }
     70         for(int k=1;k<=cnt;k++)
     71         {
     72             if(!q[b[k]].empty())
     73             {
     74                 pq.push(Node(q[b[k]].front(),b[k]));
     75             }
     76             else
     77             {
     78                 //maxn代表后面不出现 
     79                 pq.push(Node(maxn,b[k]));
     80             }
     81             //b[1,cnt]中记录的始终是当前图书馆的书,每个元素都不同,是一个一一映射 
     82             mp[b[k]]=k;
     83         }
     84         for(;i<=n;i++)
     85         { 
     86             if(!q[a[i]].empty())
     87             {
     88                 q[a[i]].pop();
     89             }
     90             if(!vis[a[i]])
     91             {
     92                 ans++;
     93                 Node node=pq.top();
     94                 pq.pop();
     95                 //根据node.num映射到对应b中的位置 
     96                 int id=mp[node.num];
     97                 vis[b[id]]=0;
     98                 b[id]=a[i];
     99                 vis[a[i]]=1;
    100                 //更新后的映射 
    101                 mp[a[i]]=id;
    102             }
    103             //要放在后面,否则会影响前面的pop 
    104             if(!q[a[i]].empty())
    105             {
    106                 pq.push(Node(q[a[i]].front(),a[i]));
    107             }
    108             else
    109             {
    110                 pq.push(Node(maxn,a[i]));
    111             }
    112         }
    113         printf("%d
    ",ans);
    114     }
    115     return 0;
    116 }
    View Code
  • 相关阅读:
    多线程 C#解决方案小结
    程序员的灯下黑:Handson,Handson,Handson!
    有一家银行每天早上都在你的帐户里存入86,400
    3D流水线[引用]
    诸葛亮著作
    Vista 用户头像存储路径
    C# 关闭显示器的函数
    程序员的灯下黑:管理还是技术?兴趣优先
    VS1.4挤房+MH的登陆器
    失眠的调养
  • 原文地址:https://www.cnblogs.com/itcsl/p/6918835.html
Copyright © 2011-2022 走看看