szoj461四校联考0430挑战

Posted 逢山开路 遇水架桥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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\n", cn[0]);
//    for (int i=1; i<=cn[0]; ++i) printf("%d ", c[0][i]);
//    puts("\n====================");
    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\n", 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\n", 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

 

以上是关于szoj461四校联考0430挑战的主要内容,如果未能解决你的问题,请参考以下文章

四校联考比赛题解FJ NOIP 四校联考 2017 Round 7

10.29 FJ四校联考

[20180901]四校联考

2017-2-19四校联考

[20180819]四校联考

四校联考——20170730模拟赛