AtCoder Regular Contest 075 2017年6月4日 C、D、E题解

http://arc075.contest.atcoder.jp/assignments

昨晚做的atcoder,今天写个简单题解。

F题不会做,800point的,就跪了,要等zk大佬来做。zk能做2400的

 

C题、我看到数据范围就直接100^3的背包,但是如果数据大点还是可以做的,贪心,首先全部值加起来,如果是%10==0的话,就需要去搭错一题,一题最少分的,而且%10 != 0的。

C
#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;
const int maxn = 1e2 + 20;
int dp[maxn * maxn];
void work() {
    dp[0] = true;
    int n;
    cin >> n;
    for (int i = 1; i <= n; ++i) {
        int val;
        cin >> val;
        for (int i = 10000; i >= val; --i) {
            if (dp[i - val]) dp[i] = true;
        }
    }
    int ans = 0;
    for (int i = 10000; i >= 0; --i) {
        if (dp[i]) {
            ans = max(ans, i % 10 == 0 ? 0 : i);
        }
    }
    printf("%d\n", ans);
}
 
int main() {
#ifdef local
    freopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#endif
    work();
    return 0;
}

 

D题、推公式二分,

设x[i]表示在h[i]个位置投放的数量,sum表示x[i]的总和,那么sum就是答案,

对于第h[i]个,需要它死亡,条件是,h[i] - (x[i] * A + (sum - x[i]) * B) <= 0

二分答案sum,然后需要判断n个h[i]都要死亡,每个h[i]死亡,需要的x[i]继续二分,判断即可。sum是满足单调的很容易看出来,

x[i]也满足单调因为A > B,可以化简公式看看,复杂度O(n * log * log),注意不要爆LL

#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;
LL n, a, b;
LL all;
int hi[1000000 + 20];
LL isok(int index, LL sum) {
    LL be = 0, en = sum;
    while (be <= en) {
        LL mid = (be + en) >> 1;
        if (a * mid + (sum - mid) * b >= hi[index]) en = mid - 1;
        else be = mid + 1;
    }
    return be;
}
bool check(LL sum) {
    LL need = 0;
    for (int i = 1; i <= n; ++i) {
        need += isok(i, sum);
        if (need > sum) return false;
    }
    return true;
}
void work() {
    cin >> n >> a >> b;
    for (int i = 1; i <= n; ++i) {
        cin >> hi[i];
        all += hi[i];
    }
    if (n == 1) {
        cout << (hi[1] + a - 1) / a << endl;
        return;
    }
    LL be = 0, en = 1e9;
    while (be <= en) {
        LL mid = (be + en) >> 1;
        if (check(mid)) en = mid - 1;
        else be = mid + 1;
    }
    cout << be << endl;
}
 
int main() {
#ifdef local
    freopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#endif
    work();
    return 0;
}
D

 

E题、化简公式 + BIT

设sum[i]表示前缀和,区间[L, R]满足条件,等价于sum[R] - sum[L - 1] >= (R- L + 1) * k

等价于sum[R] - R * k >= sum[L -1] - (L - 1) * k

相当于找前面有多少个数字比当前数字小,离散化 + bit即可。

复杂度 nlogn

#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;
const int maxn = 2e5 + 20;
LL sum[maxn];
int c[maxn];
int n, k;
int lowbit(int x) {
    return x & (-x);
}
void upDate(int pos, int val) {
    while (pos <= n) {
        c[pos] += val;
        pos += lowbit(pos);
    }
}
int ask(int pos) {
    int ans = 0;
    while (pos) {
        ans += c[pos];
        pos -= lowbit(pos);
    }
    return ans;
}
LL vc[maxn], lenvc;
void work() {
    scanf("%d%d", &n, &k);
    for (int i = 1; i <= n; ++i) {
        int val;
        scanf("%d", &val);
        sum[i] = sum[i - 1] + val;
    }
    for (int i = 1; i <= n; ++i) {
        sum[i] -= 1LL * i * k;
        vc[++lenvc] = sum[i];
//        cout << sum[i] << " ";
    }
//    cout << endl;
    sort(vc + 1, vc + 1 + lenvc);
    LL ans = 0;
    for (int i = 1; i <= n; ++i) {
        int pos = lower_bound(vc + 1, vc + 1 + lenvc, sum[i]) - vc;
        if (sum[i] >= 0) {
            ans++;
        }
        ans += ask(pos);
        upDate(pos, 1);
    }
    cout << ans << endl;
}
 
int main() {
#ifdef local
    freopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#endif
    work();
    return 0;
}
E

 

posted on 2017-06-04 10:42  stupid_one  阅读(182)  评论(0编辑  收藏  举报

导航