Codeforces Round #456 (Div. 2)

C. Perun, Ult!

分析

首先对于每个敌人单独预处理时间线(即在什么时候可以杀死这个敌人,什么时候杀不死了),然后通过一个总时间线去更新答案。

code

#include<bits/stdc++.h>
using namespace std;

const int N = 1e5 + 10;

map<long long, int> add, erase;

set<long long> timeline;

vector<pair<long long, int> > V[N];

int max_health[N], regen[N];

int main() {
    int n, m, bounty, increase, damage;
    cin >> n >> m >> bounty >> increase >> damage;
    for (int i = 0; i < n; i++) {
        int h;
        scanf("%d%d%d", &max_health[i], &h, &regen[i]);
        V[i].push_back(make_pair(0, h));
    }
    for (int i = 0; i < m; i++) {
        int t, id, h;
        scanf("%d%d%d", &t, &id, &h);
        V[id - 1].push_back(make_pair(t, h));
    }
    for (int i = 0; i < n; i++) {
        auto& v = V[i];
        sort(v.begin(), v.end());
        if(increase > 0) {
            if(damage >= max_health[i] || (!regen[i] && v.back().second <= damage)) {
                return puts("-1") * 0;
            }
        }
        for (int j = 0; j < v.size(); j++) {

            if(v[j].second > damage) continue;

            add[v[j].first]++;
            long long interval = 2e9;
            if(j != v.size() - 1) interval = min(interval, v[j + 1].first - v[j].first - 1);
            if(regen[i]) interval = min(interval, 1LL * (damage - v[j].second) / regen[i]);
            erase[v[j].first + interval]++;

            timeline.insert(v[j].first);
            timeline.insert(v[j].first + interval);
        }
    }
    long long ans = 0, cnt = 0;
    for (long long x : timeline) {
        cnt += add[x];
        ans = max(ans, cnt * (bounty + x * increase));
        cnt -= erase[x];
    }
    cout << ans << endl;
    return 0;
}

D. Fishes

分析

虽然 \(n\) 和 \(m\) 的数据都很大( \(n*m\)的矩阵),但是 \(k\) 很小,那我们就应该考虑是否可能要枚举 \(k\) 了。

求期望分为求分子和分母。分母是所有的撒网方案数,分母无法改变,我们要求分子尽可能大。

分子实际上是要求在某种鱼的布局情况下,所有可能的撒网方案下,鱼出现的次数之和最大。那么可以考虑一条鱼在不同位置对答案的贡献最大是多少,也就是说有几种方案的网可以罩住这条鱼所在的位置,这里要对行列都预处理下,再用优先队列维护下答案,因为 \(n\) 和 \(m\) 都很大我们无法全部枚举出来,最后取最大的 \(k\) 个即可。

code

#include<bits/stdc++.h>
using namespace std;

const int N = 1e5 + 10;

int a[N], b[N];

struct P {
    long long x;
    int i;
    P() {}
    P(long long x, int i): x(x), i(i) {}
    friend bool operator <(P a, P b)  {
        return a.x < b.x;
    }
};

priority_queue<P> q;

int main() {
    int n, m, r, k;
    cin >> n >> m >> r >> k;
    for (int i = 1; i <= n; i++) {
        a[i] = min(n - r + 1, i) - max(i - r + 1, 1) + 1;
    }
    for (int i = 1; i <= m; i++) {
        b[i] = min(m - r + 1, i) - max(i - r + 1, 1) + 1;
    }
    sort(a + 1, a + n + 1);
    sort(b + 1, b + m + 1);
    for (int i = 1; i <= n; i++) {
        q.push(P(a[i] * b[m], m));
    }
    long long z = 1LL * (n - r + 1) * (m - r + 1);
    long long s = 0;
    while(k--) {
        P p = q.top(); q.pop();
        s += p.x;
        if(p.i > 1) {
            p.x /= b[p.i];
            p.i--;
            p.x *= b[p.i];
            q.push(p);
        }
    }
    printf("%.10f\n", 1.0 * s / z);
    return 0;
}

E. Prime Gift

分析

二分答案 \(ans\),问题转化成小于等于 \(ans\) 的有多少个数。

dfs 暴力枚举素因子构造数,当然不能直接枚举所有素因子,考虑分成两组(按下标奇偶交替分组),使得后面构造出的两组数数量尽可能相等。假设数量最多为 \(n\),那么将两组排序后,\(O(n)\) 的复杂度就可以回答转化后的问题,当然排序会有 \(O(nlogn)\) 的复杂度。

由这道题可见 CF 的速度还是很快的,本地跑 3 秒,CF 1.3 秒。

code

#include<bits/stdc++.h>
using namespace std;

int n;
long long k;
vector<int> v1, v2;
vector<long long> res1, res2;
void dfs(int i, long long x, long long r, vector<int> v, vector<long long>& res) {
    res.push_back(x);
    for(int j = i; j < v.size(); j++) {
        if(v[j] <= r / x) dfs(j, x * v[j], r, v, res);
        else break;
    }
}

long long judge(long long r) {
    int s = res2.size() - 1;
    long long ans = 0;
    for (int i = 0; i < res1.size(); i++) {
        while(s >= 0 && res2[s] > r / res1[i]) s--;
        ans += s + 1;
    }
    return ans;
}

int main() {
    cin >> n;
    for (int i = 0; i < n; i++) {
        int p;
        cin >> p;
        !(i & 1) ? v1.push_back(p) : v2.push_back(p);
    }
    cin >> k;
    res1.clear();
    res2.clear();
    dfs(0, 1, 1e18, v1, res1);
    dfs(0, 1, 1e18, v2, res2);
    sort(res1.begin(), res1.end());
    sort(res2.begin(), res2.end());
    long long l = 1, r = 1e18;
    while(l < r) {
        long long mid = l + r >> 1;
        if(judge(mid) < k) l = mid + 1;
        else r = mid;
    }
    cout << l << endl;
    return 0;
}

原文地址:https://www.cnblogs.com/ftae/p/8394910.html

时间: 2024-10-07 21:37:35

Codeforces Round #456 (Div. 2)的相关文章

【Codeforces Round #456 (Div. 2) C】Perun, Ult!

[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] set1 < pair < int,int > > set1;记录关键点->某个人怪物永远打不死了,第一维是时间,第二维是下标 int dic[1e5+10] //记录对应下标的怪物它此时此刻在何时打不死了 set2 < pair< int,int > > set2;关键点2->有怪物要更新了的时间点,以及记录的信息下标idx2 之所以这样记录.是为了尽可能多地让怪物存活时间长一

Codeforces Round #456 (Div. 2) B题

B. New Year's Evetime limit per test1 secondmemory limit per test256 megabytesinputstandard inputoutputstandard outputSince Grisha behaved well last year, at New Year's Eve he was visited by Ded Moroz who brought an enormous bag of gifts with him! Th

Codeforces Round #260 (Div. 2) A. Laptops(简单题)

题目链接:http://codeforces.com/problemset/problem/456/A A. Laptops time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output One day Dima and Alex had an argument about the price and quality of laptops.

Codeforces Round #260 (Div. 2) B. Fedya and Maths(循环节)

题目链接:http://codeforces.com/problemset/problem/456/B B. Fedya and Maths time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Fedya studies in a gymnasium. Fedya's maths hometask is to calculate t

Codeforces Round #428 (Div. 2)

Codeforces Round #428 (Div. 2) A    看懂题目意思就知道做了 #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i

Codeforces Round #424 (Div. 2) D. Office Keys(dp)

题目链接:Codeforces Round #424 (Div. 2) D. Office Keys 题意: 在一条轴上有n个人,和m个钥匙,门在s位置. 现在每个人走单位距离需要单位时间. 每个钥匙只能被一个人拿. 求全部的人拿到钥匙并且走到门的最短时间. 题解: 显然没有交叉的情况,因为如果交叉的话可能不是最优解. 然后考虑dp[i][j]表示第i个人拿了第j把钥匙,然后 dp[i][j]=max(val(i,j),min(dp[i-1][i-1~j]))   val(i,j)表示第i个人拿

Codeforces Round #424 (Div. 2) C. Jury Marks(乱搞)

题目链接:Codeforces Round #424 (Div. 2) C. Jury Marks 题意: 给你一个有n个数序列,现在让你确定一个x,使得x通过挨着加这个序列的每一个数能出现所有给出的k个数. 问合法的x有多少个.题目保证这k个数完全不同. 题解: 显然,要将这n个数求一下前缀和,并且排一下序,这样,能出现的数就可以表示为x+a,x+b,x+c了. 这里 x+a,x+b,x+c是递增的.这里我把这个序列叫做A序列 然后对于给出的k个数,我们也排一下序,这里我把它叫做B序列,如果我

[Codeforces] Round #352 (Div. 2)

人生不止眼前的狗血,还有远方的狗带 A题B题一如既往的丝帛题 A题题意:询问按照12345678910111213...的顺序排列下去第n(n<=10^3)个数是多少 题解:打表,输出 1 #include<bits/stdc++.h> 2 using namespace std; 3 int dig[10],A[1005]; 4 int main(){ 5 int aa=0; 6 for(int i=1;;i++){ 7 int x=i,dd=0; 8 while(x)dig[++dd

Codeforces Round #273 (Div. 2)

Codeforces Round #273 (Div. 2) 题目链接 A:签到,仅仅要推断总和是不是5的倍数就可以,注意推断0的情况 B:最大值的情况是每一个集合先放1个,剩下都丢到一个集合去,最小值是尽量平均去分 C:假如3种球从小到大是a, b, c,那么假设(a + b) 2 <= c这个比較明显答案就是a + b了.由于c肯定要剩余了,假设(a + b)2 > c的话,就肯定能构造出最优的(a + b + c) / 3,由于肯定能够先拿a和b去消除c,而且控制a和b成2倍关系或者消除