zoukankan      html  css  js  c++  java
  • Canada Cup 2016 D. Contest Balloons 好题。优先队列 + 简单贪心

    http://codeforces.com/contest/725/problem/D

    这题一看就是贪心的了,w - t最小的那个,肯定是优先打死。

    但是一直都不会写,为什么呢,因为这个太像二分答案了,一看到这题就想到了二分答案,二分排名,二分扔掉气球......

    但是是不行的啊。因为扔掉n个,可能会变优,但是不能保证扔掉更小或者扔掉更多,那个更优呢?(可能需要三分答案?晚上回来试试)

    其实这题只需要用优先队列维护。

    用两个队列,que保存本来排名就比我高的那些队,优先弹出w - t最小的。

    第二个队列保存后面那些队,优先弹出t值最大的那些队(这个用来改变我的t后(就是送完气球后),把其他排名升上来进队que)

    然后每一次,够更新答案即可。

    其实就是贪心 + 模拟题目意思(把升上来的队加入来)

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    
    #include <iostream>
    #include <sstream>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    const int maxn = 3000000 + 20;
    struct node {
        LL t;
        LL w;
        LL dis;
        int id;
        bool operator < (const struct node & rhs) const {
            return dis > rhs.dis;
        }
    }a[maxn];
    struct cmp {
        bool operator() (struct node a, struct node b) {
            return a.t < b.t;
        }
    };
    priority_queue<struct node> que;
    priority_queue<struct node, vector<struct node>, cmp> out;
    int n;
    int ans = 1;
    void work() {
        cin >> n;
        int pos;
        for (int i = 1; i <= n; ++i) {
            cin >> a[i].t >> a[i].w;
            a[i].dis = a[i].w - a[i].t + 1;
            a[i].id = i;
            if (a[i].t > a[1].t) {
                que.push(a[i]);
                ++ans;
            } else {
                if (i == 1) continue;
                out.push(a[i]);
            }
        }
    //    cout << que.size() << " " << out.size() << endl;
        LL left = a[1].t;
    //    cout << ans << endl;
        while (left > 0 && !que.empty()) {
            struct node t = que.top();
            if (left >= t.dis) {
                left -= t.dis;
                que.pop();
                while (!out.empty()) {
                    struct node temp = out.top();
                    if (temp.t > left) {
                        que.push(temp);
                        out.pop();
                    } else break;
                }
            } else break;
            int cc = que.size() + 1;
            ans = min(ans, cc);
        }
        cout << ans << endl;
    }
    
    int main() {
    #ifdef local
        freopen("data.txt","r",stdin);
    #endif
        IOS;
        work();
        return 0;
    }
    View Code

    题解:

    725D - Contest Balloons

    I (a problem author) want to thank the ICPC Live staff. During the World Finals a commentator ([user:Egor] maybe?) said that contests always have balloons and maybe someone should invent a problem about them for the next finals (I'm not organizing those though). Thanks for the idea!

    If you just want the solution, read only the last paragraph. Previous ones describe how to find a correct approach. It may lead to a slightly more complicated solution, but you will learn something for sure.

    To come up with a solution, you must try iterating over some value or maybe binary searching an optimal value. Let's list a few reasonable ideas. Try to binary search the answer (for fixed final place of Limak you must say if he can get at least this place). Or iterate over the number of disqualified teams (if Limak should beat exactly i teams, what is the best place he can get?). Or iterate over the number of balloons Limak should give away.

    The last idea turns out to be fruitful. The first observation is that you don't have to consider every possible number of balloons to give away. We can assume that the final number of balloons will be either 0 or ti for some i. Otherwise Limak could give away some more balloons and his place won't be worse (if there are no more teams, let's imagine he can destroy them). We use here a simple observation that the i-th team either will be disqualified or will still have exactly ti balloons, i.e. values ti won't change.

    We have O(n) possibilities for the final number of balloons. Let's first solve a problem in  by considering possibilities separately, each in . Let's say Limak will have k balloons at the end. He can give away t1 - k balloons. He should try to get rid of teams with ti > k because worse teams don't affect his place. You should sort teams with ti > k by the number of balloons they need to get disqualified i.e. wi - ti + 1. It's easiest for Limak to get rid of teams with small value of wi - ti + 1 so you should just check how many of those values can be chosen so that the sum of them won't exceed t1 - k. It turns out to be possible to improve the above by considering possibilities in the decreasing order. Think what happens when you decrease k. Some more teams become a possible target and you should consider their values wi - ti + 1. A sorted set of those values should be useful. Try to invent a solution yourself now. Then you can see one simple version in the next paragraph.

    Now let's see an  greedy solution. Create a variable k representing the final number of balloons Limak has, initially k = t1. Create and maintain a multiset with valueswi - ti + 1 of teams better than the current k, i.e. teams with ti > k. If it makes sense to give away some more balloons, Limak has to eliminate at least one of those better teams (otherwise he can stop now). It's easiest to eliminate a team with the smallest wi - ti + 1, so we can just remove the smallest element from the set and decrease k by its value. Maybe some more teams become better than the current k and you should add those to the multiset. Note that the multiset contains exactly those teams which would win with Limak in the current scenario, so after every change of k you can update the answer 'ans = min(ans, my_multiset.size() + 1)'. Remember to stop if k becomes smaller than 0.

  • 相关阅读:
    REAL6410、OK6410、TE6410 的区别
    在裸奔2440时候遇到的GPIO郁闷问题(作者gooogleman)
    Jlink V8 48 RMB,力特USB转串口线 35 RMB 甩了!所剩不多,先到先得。
    一个机械专业小混混(gooogleman)学习嵌入式ARM的真实经历
    如何给自己淘宝的宝贝做google广告?
    程序员开网店的一些经验分享
    【有奖辩论】工程师和销售创业谁更有优势?
    关于高端ARM处理器选型的一些个人看法(作者:gooogleman)
    要搬家了,准备甩掉剩下的十多个源动力笔记本包,运动休闲包!
    推荐一款高性价比android /wince/Linux ARM11 S3C6410 开发板
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/6022769.html
Copyright © 2011-2022 走看看