优秀的拆分(power)

死于bitset的下标访问。看了眼之前的博客,然后随便测了点数据没出问题,然后就放心用bitset[0]这种,然后就G了。算法是对的,转换成string以后就能过了。

教训就是不知道bitset的下标访问出来是什么鬼东西。

其实直接用long long或者int都是能轻松切掉的。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main() {
    int n;
    while (cin >> n) {
        if (n & 1) {
            puts("-1");
            continue;
        }
        for (int i = log2(n); i; --i)
            if (n >> i) printf("%d ", 1 << i), n -= 1 << i;
        putchar(10);
    }
    return 0;
}
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main() {
    ll n;
    while (cin >> n) {
        if (n & 1) {
            puts("-1");
            continue;
        }
        int len = log2(n) + 1;
        bitset<32> st(n);
        string s = st.to_string();
        int i = 0;
        while (!(s[i] - '0')) ++i;
        for (int j = 0; i < s.length(); i++, ++j) {
            if (s[i]-'0') {
                printf("%lld ", 1LL << (len - j - 1));
            }
        }
        putchar(10);
    }
    return 0;
}

直播获奖(live)

维护一个有序的vector,暴力即可。

#include <bits/stdc++.h>
#define sc(x) scanf("%d", &(x))
using namespace std;
const int maxn = 2e5 + 7;
typedef long long ll;
int n, m, a[maxn];
vector<int> v;
int main() {
    sc(n), sc(m);
    for (int i = 1; i <= n; i++) {
        sc(a[i]);
        int x = max(1, (int)floor(i * m * 0.01));
        v.insert(lower_bound(v.begin(), v.end(), a[i]), a[i]);
        printf("%d ", v[v.size() - x]);
    }
    return 0;
}

想到的最优解法是队友提出来的拿树状数组当桶然后二分查。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 600 + 7;
#define lowbit(x) ((x) & (-x))
#define sc(x) scanf("%d", &(x))
ll tree[N], zero;
int n, w, a;
inline void update(int i, ll x) {
    for (int pos = i; pos < N; pos += lowbit(pos)) tree[pos] += x;
}
inline ll query(int n) {
    if (n < 0) return 0;
    ll ans = 0;
    for (int pos = n; pos; pos -= lowbit(pos)) ans += tree[pos];
    return ans;
}
inline ll query(int a, int b) { return query(b) - query(a - 1); }
inline int getans(int x) {
    int L = 0, R = N, ans = 0;
    while (L <= R) {
        int mid = L + R >> 1;
        if (query(mid, 600) >= x)
            L = mid + 1, ans = mid;
        else
            R = mid - 1;
    }
    return ans;
}
int main() {
    sc(n), sc(w);
    for (int i = 1; i <= n; ++i) {
        sc(a);
        if (!a)
            ++zero;
        else
            update(a, 1LL);
        int x = max(1, i * w / 100);
        printf("%d ", getans(x));
    }
    return 0;
}

感谢朝阳大佬的hack

方格取数(number)

因为不走回头路,拆解成下右+上右两种方案,然后比较最优即可。

#include <bits/stdc++.h>
#define sc(x) scanf("%d", &(x))
using namespace std;
const int maxn = 1e3 + 7;
typedef long long ll;
const int INF = 0x3f3f3f3f;
int g[maxn][maxn], f[maxn][maxn], a[maxn][maxn];
int main() {
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++) sc(a[i][j]);
    for (int i = 0; i <= n + 1; i++)
        for (int j = 0; j <= m + 1; j++) g[i][j] = f[i][j] = -INF;
    f[1][1] = a[1][1];
    for (int j = 1; j <= m; j++) {    //列
        for (int i = 1; i <= n; i++)  //行
            g[i][j] = f[i][j] =
                max(f[i][j], f[i][j - 1] + a[i][j]);  //从左边走过来
        for (int i = 1; i <= n; i++)
            f[i][j] = max(f[i][j], f[i - 1][j] + a[i][j]);  //从上面走过来
        for (int i = n - 1; i >= 1; i--)
            g[i][j] = max(g[i][j], g[i + 1][j] + a[i][j]);  //从下面走过来
        for (int i = 1; i <= n; i++) f[i][j] = max(g[i][j], f[i][j]);
    }
    cout << f[n][m] << endl;
    return 0;
}