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.

  • 相关阅读:
    同步linux服务器的时间
    Esper学习之四:Context
    Haproxy+Keepalived搭建Weblogic高可用负载均衡集群
    C++中的对象指针
    第十五周oj刷题——Problem M: C++习题 矩阵求和--重载运算符
    《人工智能教程(张仰森)》(二)
    JAVA 并发编程-线程池(七)
    新手学測试----Unit Test(单元測试)
    HDU2193-AVL-数据结构-AVL
    Visual Assist X破解版安装(vs2010助手)
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/6022769.html
Copyright © 2011-2022 走看看