제출 #806669

#제출 시각아이디문제언어결과실행 시간메모리
806669hugo_pmCake 3 (JOI19_cake3)C++17
100 / 100
685 ms202764 KiB
#include<bits/stdc++.h>
using namespace std;
    
#define int long long
using pii=pair<int,int>;
    
string to_string(string s) { return s; }
template <typename T> string to_string(T v) {
    bool first = true;
    string res = "[";
    for (const auto &x : v) {
        if (!first)
            res += ", ";
        first = false;
        res += to_string(x);
    }
    res += "]";
    return res;
}
    
template <typename A, typename B>
string to_string(pair<A, B> p) {
    return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";
}
    
void dbg_out() { cout << endl; }
template <typename Head, typename... Tail> void dbg_out(Head H, Tail... T) {
    cout << ' ' << to_string(H);
    dbg_out(T...);
}
    
#ifdef DEBUG
#define dbg(...) cout << "(" << #__VA_ARGS__ << "):", dbg_out(__VA_ARGS__)
#else
#define dbg(...)
#endif
    
struct noeud{
    int minVal,maxVal,pos;
    noeud *filsGauche=nullptr,*filsDroit=nullptr;
    vector<int> cumuGauche,cumuVal,cumuDroite;
    noeud (vector<int> listeVal) {
        assert(!listeVal.empty());
        minVal = *min_element(listeVal.begin(), listeVal.end());
        maxVal = *max_element(listeVal.begin(), listeVal.end());
        //dbg(minVal,maxVal,listeVal);
        cumuVal.push_back(0);
        for (auto x:listeVal) {
            cumuVal.push_back(x+cumuVal.back());
        }
        int taille=listeVal.size();
        if (minVal!=maxVal) {
            int mid=(minVal+maxVal)/2;
            vector<int> listeGauche,listeDroite;
            cumuGauche.push_back(0);
            cumuDroite.push_back(0);
            for (int x:listeVal) {
                int estGauche;
                if (x<=mid) {
                    estGauche=1;
                    listeGauche.push_back(x);
                }
                else {
                    estGauche=0;
                    listeDroite.push_back(x);
                }
                cumuGauche.push_back(cumuGauche.back()+estGauche);
                cumuDroite.push_back(cumuDroite.back()+1-estGauche);
            }
            if (!listeGauche.empty()) {
                filsGauche=new noeud(listeGauche);
            }
            if (!listeDroite.empty()) {
                filsDroit=new noeud(listeDroite);
            }
        }
        else {
            cumuGauche.resize(taille+1,0);
            cumuDroite.resize(taille+1,0);
        }
    }
    pair<int,int> somMax(int deb,int fin,int nbVal) {
        if (deb>fin) {
            return {0,0};
        } else if (fin-deb+1<=nbVal || minVal == maxVal) {
            int nouvDeb = max(deb, fin-nbVal+1); //s.t. fin-nd+1 = nbVal
            int somme = cumuVal[fin+1]-cumuVal[nouvDeb];
            return {somme, fin-nouvDeb+1};
        }
        //int nbGauche=cumuGauche[fin+1]-cumuGauche[deb];
        //int nbDroite=cumuDroite[fin+1]-cumuDroite[deb];
        int debGauche=cumuGauche[deb];
        int finGauche=cumuGauche[fin+1]-1;
        int debDroite=cumuDroite[deb];
        int finDroite=cumuDroite[fin+1]-1;
        int somDroit=0,cntDroit=0,somGauche=0,cntGauche=0;
        if (filsDroit!=nullptr) {
            tie(somDroit,cntDroit)=filsDroit->somMax(debDroite,finDroite,nbVal);
            nbVal-=cntDroit;
        }
        if (nbVal>0 and filsGauche!=nullptr) {
            tie(somGauche,cntGauche)=filsGauche->somMax(debGauche,finGauche,nbVal);
        }
        dbg(somDroit,somGauche,cntDroit,cntGauche);
        return {somDroit+somGauche,cntDroit+cntGauche};
    }
};
    
const int INFINI=(int)1000*1000*1000*1000*1000*1000;
int nbPossi,tailleCol,prix,benef,rep;
noeud *racine;
vector<pair<int,int>> possi;
    
int somMax(int deb,int fin,int nbVal) {
    return racine->somMax(deb,fin,nbVal).first;
}
    
int calcMeil(int deb,int fin) {
    return possi[deb].second+possi[fin].second-2*(possi[fin].first-possi[deb].first)+somMax(deb+1,fin-1,tailleCol-2);
}
    
void calc(int minDeb,int maxDeb,int minFin,int maxFin) {
    if (maxDeb<minDeb or maxFin<minFin) {
        return;
    }
    int deb=(minDeb+maxDeb)/2;
    pii record={-INFINI,maxFin};
    dbg(deb);
    for (int i=minFin;i<=maxFin;i++) {
        if (i-deb+1>=tailleCol) {
            dbg(deb,i);
            record=max(record,{calcMeil(deb,i),i});
        } 
    }
    rep=max(rep,record.first);
    calc(minDeb,deb-1,minFin,record.second);
    calc(deb+1,maxDeb,record.second,maxFin);
}
    
signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    cin>>nbPossi>>tailleCol;
    for (int i=0;i<nbPossi;i++) {
        cin>>benef>>prix;
        possi.push_back({prix,benef});
    }
    sort(possi.begin(),possi.end());
    vector<int> listeCoul;
    for (auto [_,coul]:possi) {
        listeCoul.push_back(coul);
    }
    rep=-INFINI;
    racine=new noeud(listeCoul);
    calc(0,nbPossi-1,0,nbPossi-1);
    cout<<rep<<endl;
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...