zoukankan      html  css  js  c++  java
  • P2107 小Z的AK计划


    题目描述

    在小Z的家乡,有机房一条街,街上有很多机房。每个机房里都有一万个人在切题。小Z刚刷完CodeChef,准备出来逛逛。

    机房一条街有 n 个机房,第 i 个机房的坐标为 xi ,小Z的家坐标为 0。小Z在街上移动的速度为1,即从 x1 到 x2 所耗费的时间为 |x1 − x2|。 每个机房的学生数量不同,ACM 题目水平也良莠不齐。小Z到达第 i 个机房后,可以花 ti 的时间想题,然后瞬间 AK;当然,也可以过机房而不入。

    小Z现在只有 m 个单位时间,之后他就该赶着去打 Codeforces 了。现在他想知道自己最多能在多少个机房 AK,希望你帮帮他。

    知识点
    二叉堆
    优先队列

    输入格式:
    第一行包含两个整数 n,m。

    接下来 n 行,每行包含两个整数 xi,ti 。

    输出格式:
    第一行包含一个整数,表示小Z最多能 AK 的机房数量。

    输入输出样例

    输入样例#1:
    2 10
    1 100
    5 5
    输出样例#1:
    1
    说明

    【数据规模】

    对于 30% 的数据,n ≤ 20。

    对于 60% 的数据,n ≤ 1000。

    对于 100% 的数据,1 ≤ n ≤ 10^5,0 ≤ m,xi ≤ 10^18,0 ≤ ti ≤ 10^9。
    这道题因为路径长度不定,若同时考虑路径长和思考时间两个因素会很麻烦,但是因为一条路绝对不会重复走(原因当然是浪费时间,还没有意义),所以我们可以考虑通过枚举使路径长这一因素变为一个固定值,这样我们只需要通过贪心来从小到大取思考时间即可,但这道题数据量比较大,则不能用插入排序(因为一定会超时),所以我们换一种考虑方式,使每次新进来的值加上我原来在上一个点所用的可以得到最多的AK机房数的几种情况中思考时间最少的时间加上路径所用时间,判断是否超时,同时,将此机房思考时间入队;若不超,则可将此机房添加到答案中去;若超时,则将所取的时间的队列中的最大值弹出,同时时间减去最大值
    #include<bits/stdc++.h>
    using namespace std;
    const int ma=1e5+10;
    struct zx{long long x;int y;};
    zx s[ma];
    long long a[ma],m;
    int n,cnt,ans;
    void su(int x)
    {
    while(x>>1>=1&&a[x>>1]<a[x])
    {
    swap(a[x>>1],a[x]);
    x>>=1;
    }
    }
    void sx(int x)
    {
    while(x<<1<=cnt)
    {
    int t=x,p=x<<1;
    if(a[p]>a[t])
    t=p;
    if(p+1<=cnt&&a[p+1]>a[t])
    t=p+1;
    if(t==x)
    break;
    swap(a[t],a[x]);
    x=t;
    }
    }
    void add(int x)
    {
    a[++cnt]=x;
    su(cnt);
    }
    void rm()
    {
    a[1]=a[cnt--];
    sx(1);
    }
    bool cmp(zx c,zx d)
    {
    return c.x<d.x;
    }
    int main()
    {
    long long p=0,x;
    int y,cn=0;
    scanf("%d%lld",&n,&m);
    for(int i=1;i<=n;i++)
    {
    scanf("%lld%d",&x,&y);
    if(x<=m)//如果路程时间已经超过可用时间,那么到此机房为止所能AK的机房数一定为零,也就没有做的必要
    {
    s[++cn].x=x;
    s[cn].y=y;
    }
    }
    sort(s+1,s+1+cn,cmp);//按照路程排序
    for(int i=1;i<=cn;i++)
    {
    p+=s[i].x+s[i].y-s[i-1].x;//加上这个机房的路径和思考时间,同时减去上一个机房的路径时间
    add(s[i].y);//入队* (1)
    ans++;
    if(p>m)
    {
    ans--;
    p-=a[1];//减去最大值*(2)
    rm();//弹出* (3)
    }
    }
    printf("%d",ans);
    return 0;
    }
    带*号的步骤可用优先队列实现(这样就不用打上面的函数啦)
    priority_queue<int,vector<int>,less<int> >q;
    (1):q.push(s[i].y);
    (2):p-=q.top();
    (3):q.pop();

  • 相关阅读:
    方法转换IE、Firefox、Chrome区别
    splice方法便签
    webstorm主题网址+使用方法
    从程序员到项目经理(一):没有捷径
    界面原型图绘制工具Pencil
    程序员:伤不起的三十岁
    从程序员到项目经理(三):认识项目经理
    从程序员到项目经理(二):如何胜任
    原型制作软件 Axure RP
    软件界面原型设计工具 UIDesigner
  • 原文地址:https://www.cnblogs.com/LWL--Figthing/p/9108933.html
Copyright © 2011-2022 走看看