• szoj461【四校联考0430】挑战


    传送门:(涉及版权忽略)

    【题解】

    我们发现n的范围很小,提示我们可以折半,然后我们就会了O(T2^(n/2)*n)的做法,然而会T。

    考虑如何优化。直接排序会多一个log(2^(n/2))也就是n,那么改成每次加一个数,归并即可。这样复杂度是对的

    T(n) = T(n-1) + 2^n  ==> T(n) = O(2^n)

    那么复杂度就是O(T2^(n/2))

    # include <stdio.h>
    # include <string.h>
    # include <algorithm>
    // # include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int M = 50 + 10, N = 2333333;
    const int mod = 1e9+7;
    
    # define FO_OPEN 0
    # define RG register
    # define ST static
    
    int n, m, a[M];
    int c[2][N], cn[2];
    int t[N];
    
    inline void merge(int pos, int l, int mid, int r) {
        int i = l, j = mid+1, k = l-1;
        while(i<=mid && j<=r) {
            if(c[pos][i] < c[pos][j]) t[++k] = c[pos][i++];
            else t[++k] = c[pos][j++];
        }
        while(i<=mid) t[++k] = c[pos][i++];
        while(j<=r) t[++k] = c[pos][j++];
        for (int o=l; o<=r; ++o) c[pos][o] = t[o];
    }
    
    inline void sol() {
        int sum = 0;
        scanf("%d%d", &n, &m);
        for (int i=1; i<=n; ++i) scanf("%d", &a[i]), sum = sum + a[i];
        if(sum < m) {
            puts("-1");
            return ;
        }
        int res = n/2;
        c[0][cn[0] = 1] = 0;
        for (int i=1; i<=res; ++i) {
            for (int j=1; j<=cn[0]; ++j) c[0][j+cn[0]] = c[0][j] + a[i];
            merge(0, 1, cn[0], cn[0] << 1);
            cn[0] <<= 1;
        }
    //    printf("cn[0] = %d
    ", cn[0]);
    //    for (int i=1; i<=cn[0]; ++i) printf("%d ", c[0][i]);
    //    puts("
    ====================");
        c[1][cn[1] = 1] = 0;
        for (int i=res+1; i<=n; ++i) {
            for (int j=1; j<=cn[1]; ++j) c[1][j+cn[1]] = c[1][j] + a[i];
            merge(1, 1, cn[1], cn[1] << 1);
            cn[1] <<= 1;
        }
    //    printf("cn[1] = %d
    ", cn[1]);
    //    for (int i=1; i<=cn[1]; ++i) printf("%d ", c[1][i]);
    //    puts("");
        int p0 = 1, p1 = cn[1], ans = 2147483647;
        for (; p0 <= cn[0]; p0 ++) {
            while(p1 && c[0][p0] + c[1][p1] >= m) --p1;    
            if(p1 != cn[1]) 
                ans = min(ans, c[0][p0] + c[1][p1 + 1]);
        }
        printf("%d
    ", ans);
    } 
    
    int main() {
        FO_OPEN ? freopen("challenge.in", "r", stdin), freopen("challenge.out", "w", stdout) : 0;
        int T; scanf("%d", &T);
        while(T--) sol();
        return 0;
    }
    View Code
  • 相关阅读:
    Android开源demo---芒果TV-VIP电影播放器
    实现sqrt()函数
    std::string内容包含双引号
    解决win10 SVN不显示绿色和红色的状态显示标志
    win 10 解决 caps键无法退出大写的问题
    webrtc 编译问题:running depot tools as root is sad 的解决办法
    Linux下运行脚本显示“: /usr/bin/env: "bash ": 没有那个文件或目录
    解决报错:no acceptable C compiler found in $PATH when installing python
    linux 打开文件管理器
    windows打开U盘提示 文件或目录损坏且无法读取 解决办法
  • 原文地址:https://www.cnblogs.com/galaxies/p/szoj461.html
Copyright © 2020-2023  润新知