【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