zoukankan      html  css  js  c++  java
  • E. Santa Claus and Tangerines 二分答案 + 记忆化搜索

    http://codeforces.com/contest/752/problem/E

    首先有一个东西就是,如果我要检测5,那么14我们认为它能产生2个5.

    14 = 7 + 7.但是按照平均分的话,它是不能产生5的,那就把那两个7当成是两个5,因为7比5还大,对min(b[i])是没有影响的。

    可以思考下样例2.

    那么二分答案mid,设dp[val][x]表示val这个数字能产生多少个x。dp[val][x] = dp[val / 2][x] + dp[(val + 1) / 2][x]

    那么dp数组开不了那么大,可以考虑记忆化搜索。用另外一个数组vis[]标记是否已经搜索过即可。因为dp数组需要重复使用,已经有值了。vis[]可以用DFN简单代替memset

    判断每个数字能拆成多少个x,复杂度是logn的,所以复杂度是nlognlogn

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <assert.h>
    #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 = 1e6 + 20;
    int a[maxn];
    int n, k;
    int dp[maxn * 10];
    int vis[maxn * 10];
    int DFN;
    int func(int val, int x) {
        if (vis[val] == DFN) return dp[val];
        if (val < x) return 0;
        if (val / 2 < x) { // 6也算可以生成5
            vis[val] = DFN;
            dp[val] = 1;
            return 1;
        }
        if (val & 1) {
            int ans = func(val / 2, x) + func((val + 1) / 2, x);
            vis[val] = DFN;
            dp[val] = ans;
            return ans;
        } else {
            int ans = 2 * func(val / 2, x);
            vis[val] = DFN;
            dp[val] = ans;
            return ans;
        }
    }
    bool check(LL val) {
        int ans = 0;
        ++DFN;
        for (int i = 1; i <= n; ++i) {
            if (a[i] < val) break;
            ans += func(a[i], val);
            if (ans >= k) return true;
        }
        return false;
    }
    void work() {
        scanf("%d%d", &n, &k);
        for (int i = 1; i <= n; ++i) {
            scanf("%d", &a[i]);
        }
        sort(a + 1, a + 1 + n, greater<int>());
    //    for (int i = 1; i <= n; ++i) {
    //        cout << a[i] << " ";
    //    }
    //    cout << endl;
        LL be = 1, en = 1e14L;
        while (be <= en) {
            LL mid = (be + en) >> 1;
            if (check(mid)) {
                be = mid + 1;
            } else en = mid - 1;
        }
        if (en == 0) {
            printf("-1
    ");
        } else printf("%I64d
    ", en);
    //    cout << func(20, 5) << endl;
    }
    
    int main() {
    #ifdef local
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
        work();
        return 0;
    }
    View Code
  • 相关阅读:
    System.arraycopy
    关于验证控件和javaSript验证的共存问题
    正则表达式经典
    css的一些基础的东西
    运用JAVASCRIPT,写一个类,类名:student,他的属性:name,age,tall,他的方法:getName,getAge,getTall
    转: ASP.NET 应用程序生命周期概述
    转:关于 Global.asax 文件
    今天又要过去了,学习点东西!
    javaScript对象和属性
    转载:.NET 2005 实现在线人数统计
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/6221016.html
Copyright © 2011-2022 走看看