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

【链接】 我是链接,点我呀:)
【题意】

在这里输入题意

【题解】

set1 < pair < int,int > > set1;记录关键点->某个人怪物永远打不死了,第一维是时间,第二维是下标

int dic[1e5+10] //记录对应下标的怪物它此时此刻在何时打不死了

set2 < pair< int,int > > set2;关键点2->有怪物要更新了的时间点,以及记录的信息下标idx2

之所以这样记录。是为了尽可能多地让怪物存活时间长一点

if (start > damage) continue;else

//special表示这个怪物一直能被打死。
//delta表示目前为止一直能被打死的怪物的个数
if (max_h <= damage ||(start<=damage && rec==0)) {delta++; special[i] = 1;continue;}else{
int time = damage-start/rec;->取整数部分就可以了
set1.insert(time,idx);
dic[idx] = time;
}

set2.insert(timej,j);

set1和set2里面找关键点。
先找小的时间mi

如果是set1的话
    temp = set1.size();
    if (上一个时间和这个时间相同) temp = 上一次set1的size()
    ans = max(ans,(temp+delta)*(chushi+mi*increase));
    然后删掉set1.begin();

如果是set2的话
    因为可能经过这次更新之后某些怪物的曲线变了。
    则在变之前先尝试更新一下答案。
    时间是t2-1
    num = (ll)set1.size();
    ans = max(ans,(num+delta)*(bounty+(t2-1)*increase));

    int idx = enemy[set2.begin().second];
    pair<dic[idx],idx>;
    从set1中删掉这个东西->如果有
    if (special[idx]==1) delta--;
    if (health>damage) continue;
    if (maxh<=damage ||(updateheadl<=damage && rec==0)) {delta++;special[idx] = 1;continue;else{
        int time = (damage-update)/rec
        set1.insert(timebegin+time,idx)
    }

最后统计special的个数cnt

如果cnt>0且increase!=0 那么输出无限大
否则increase==0 则 再用cnt*bounty和ans比一下取较大值;->防止没有更新操作的时候一次ans都没有取到

【代码】

#include <bits/stdc++.h>
#define ll long long
#define time mytime
using namespace std;

const int N = 1e5;

set<pair<ll,int> > set1,set2;
int n,m;
ll bounty,increase,damage;
ll max_h[N+10],start_h[N+10],regen[N+10];
ll time[N+10],enemy[N+10],health[N+10],dic[N+10],delta = 0;
bool special[N+10];

int main(){
    #ifdef LOCAL_DEFINE
        freopen("rush_in.txt", "r", stdin);
    #endif
    ios::sync_with_stdio(0),cin.tie(0);
    memset(dic,255,sizeof dic);
    cin >> n >> m;
    cin >> bounty >> increase >> damage;
    for (int i = 1;i <= n;i++){
        cin >> max_h[i] >> start_h[i] >> regen[i];

        if (start_h[i]>damage) continue;
        if (max_h[i]<=damage ||(start_h[i]<=damage && regen[i]==0)){
            special[i] = 1;
            delta++;
            continue;
        }
        ll time = (damage-start_h[i])/regen[i];
        dic[i] = time;
        set1.insert({time,i});
    }

    for (int i = 1;i <= m;i++){
        cin >> time[i] >> enemy[i] >> health[i];
        set2.insert({time[i],i});
    }

    ll ans = 0;
    int pre = -1;
    ll prenum = 0;
    while (!set1.empty() || !set2.empty()){
        ll t1 = -1,t2 = -1;
        if (!set1.empty()) t1 = (*set1.begin()).first;
        if (!set2.empty()) t2 = (*set2.begin()).first;
        //等于的话先处理更新的
        if (t1!=-1 &&(t2==-1 || t1 <t2)){
            ll time2 = (*set1.begin()).first;
            ll num = (ll)set1.size();
            if (pre!=-1 && time2==pre){
                num = prenum;
            }else {
                pre = time2;
                prenum = num;
            }
            ans = max(ans,(num+delta)*(bounty+t1*increase));
            set1.erase(set1.begin());
        }else{
            ll num = (ll)set1.size();
            ans = max(ans,(num+delta)*(bounty+(t2-1)*increase));

            int tempidx = (*set2.begin()).second;
            set2.erase(set2.begin());
            int idx =enemy[tempidx];
            auto it = set1.upper_bound({dic[idx],idx});
            if (it!=set1.begin()){
                it--;
                pair<ll,int> temp = (*it);
                if (temp.first==dic[idx] && temp.second==idx){
                    set1.erase(it);
                }
            }

            if (special[idx]) delta--;
            special[idx] = 0;
            dic[idx] = -1;
            if (health[tempidx]>damage) continue;
            if (max_h[idx]<=damage ||(health[tempidx]<=damage && regen[idx]==0)){
                special[idx] = 1;
                delta++;
                continue;
            } else{
                ll time1 = (damage-health[tempidx])/regen[idx];
                dic[idx] = time[tempidx] + time1;
                set1.insert({dic[idx],idx});
            }
        }
    }

    int cc =0;
    for (int i = 1;i <= n;i++)
        if (special[i])
            cc++;
    if (cc>0 && increase>0)
        return cout<<-1,0;
    else ans = max(ans,(ll)cc*bounty);
    cout << ans << endl;
    return 0;
}

原文地址:https://www.cnblogs.com/AWCXV/p/8213528.html

时间: 2024-08-30 11:28:23

【Codeforces Round #456 (Div. 2) C】Perun, Ult!的相关文章

【Codeforces Round #446 (Div. 2) A】Greed

[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 贪心选容量大的瓶子就好 [代码] #include <bits/stdc++.h> #define int long long using namespace std; const int N = 1e5; int n; int a[N+10],b[N+10]; main(){ #ifdef LOCAL_DEFINE freopen("F:\\c++source\\rush_in.txt", "r

【Codeforces Round #446 (Div. 2) C】Pride

[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 想一下,感觉最后的结果肯定是从某一段开始,这一段的gcd为1,然后向左和向右扩散的. 则枚举那一段在哪个地方. 我们设这一段中所有的数字都做了一次gcd. 假设在i..j这一段. 则求gcd的顺序是(i,i+1),(i+1,i+2)...(j-1,j) 这样a[j]=gcd(a[i],a[i+1]..a[j])了 即顺序求了一遍gcd. 这样,预处理一下i到j的gcd. 如果gcd[i][j]==1,则获取到一个可行方案. 求一

【Codeforces Round #447 (Div. 2) A】QAQ

[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] C语言程序练习题 [代码] #include <bits/stdc++.h> using namespace std; string s; int main(){ #ifdef LOCAL_DEFINE freopen("F:\\c++source\\rush_in.txt", "r", stdin); #endif ios::sync_with_stdio(0),cin.tie(0);

【Codeforces Round #451 (Div. 2) D】Alarm Clock

[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 尺取法+二分. 类似滑动窗口. 即左端点为l,右端点为r. 维护a[r]-a[l]+1总是小于等于m的就好. (大于m就右移左端点) 然后看看里面的数字个数是不是小于k; 不是的话让l..r中最右边那个数字删掉就好. ->链表优化一下即可. [代码] /* 1.Shoud it use long long ? 2.Have you ever test several sample(at least therr) yourself

【Codeforces Round #452 (Div. 2) A】 Splitting in Teams

[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 贪心 1优先和2组队. 如果1没有了 就结束. 如果1还有多余的. 那么就自己3个3个组队 [代码] #include <bits/stdc++.h> using namespace std; const int N = 2e5; int n; int a[3]; int main(){ #ifdef LOCAL_DEFINE freopen("rush_in.txt", "r", st

【Codeforces Round #452 (Div. 2) B】Months and Years

[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 闰,平,平 平,闰,平 平,平,闰 平,平,平 4种情况都考虑到就好. 可能有重复的情况. 但是没关系啦. [代码] #include <bits/stdc++.h> using namespace std; const int N = 24; int p[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; int r[12] = {31,29,31,30,31,30,31,31,30,3

【Codeforces Round #452 (Div. 2) C】 Dividing the numbers

[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] n为偶数. l = 1, r = n (l,r)放在一组 l++,r-- 新的l,r放在另外一组 直到l+1==r 这个时候,判断两组的和,如果一样的话,分散在两组 差为1否则差为0 n为奇数 l = 2,r = n (l,r)放在一组 l++,r-- 新的l,r放在另外一组 直到l+1==r 这个时候,判断两组的和,如果一样的话,分散在两组 差为0(把1放在那个较少的组) 否则,差为1 1随意放在哪一组都可以 [代码] #in

【Codeforces Round #457 (Div. 2) A】 Jamie and Alarm Snooze

[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 暴力往前走x分钟就好. 直到出现7为止. [代码] #include <bits/stdc++.h> using namespace std; int hh,mm,x,cnt; bool find7(){ if (hh%10==7 || (hh/10)==7) return true; if (mm%10==7 || (mm/10)==7) return true; return false; } int main(){ #i

【Codeforces Round #457 (Div. 2) B】Jamie and Binary Sequence

[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 把n分解成二进制的形式. n=2^a0+2^a1+...+2^a[q-1] 则固定就是长度为q的序列. 要想扩展为长为k的序列. 可以把2^x转化为2^(x-1)+2^(x-1)的形式. 这样序列的长度就+1了 它要求max{ai}最大 那么我们可以枚举ai的最大值是什么->i (递减着枚举) 然后比i大的ai都换成两个ai-1的形式. 然后看看序列的长度是否小于等于k; 如果小于k的话. 就把min{ai}分解成两个min{a