제출 #1264482

#제출 시각아이디문제언어결과실행 시간메모리
1264482pythontestDungeon 3 (JOI21_ho_t5)C++20
100 / 100
690 ms124220 KiB
#include <deque>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct nodeliniowka {
    long long a,b;
    nodeliniowka operator +(const nodeliniowka& x)  const{
        nodeliniowka res;
        res.a = this->a+x.a;
        res.b = this->b+x.b;
        return res;
    }
    void operator +=(const nodeliniowka& x) {
        this->a+=x.a;
        this->b+=x.b;
    }
    bool operator <(const nodeliniowka& x) const {
        if (this->a==x.a) return this->b<x.b;
        return this->a<x.a;
    }
};
struct zapytanie {
    long long u;
    int a; int b;
    int indeks;
    bool operator <(const zapytanie& x) const {
        return this->u<x.u;
    }
};

typedef pair<long long, long long> treepair;
typedef pair<long long, pair<long long, int>> treepairext;
struct przejscie {
    long long warunek;
    int indeks;
    int priorytet;
    nodeliniowka v;
    bool operator < (const przejscie& x) const {
        if (this->warunek==x.warunek) return this->priorytet<x.priorytet;
        return this->warunek<x.warunek;
    }
};
constexpr int MJ=20;
constexpr int N = 1<<(MJ-2);
constexpr long long INF=1e14;
int n,q;
nodeliniowka drzewoliniowek[1<<MJ];
treepairext drzewominmaksow[1<<MJ];
vector<long long> prefdist, dist, cost;
long long dl[N],dr[N], jp[N][MJ], sjp[N][MJ];
void updatelin(int n, nodeliniowka v) {
    n+=1<<(MJ-1);
    drzewoliniowek[n] = v;
    n>>=1;
    while (n>0) {
        drzewoliniowek[n] = drzewoliniowek[2*n]+drzewoliniowek[2*n+1];
        n>>=1;
    }
}
nodeliniowka readlin(int a, int b) {
    a+=1<<(MJ-1);b+=1<<(MJ-1);
    if (a>b) return {0,0};
    nodeliniowka res=drzewoliniowek[a];
    if (a==b) return res;
    res+=drzewoliniowek[b];
    while ((a>>1)!=(b>>1)) {
        if (a%2==0) res+= drzewoliniowek[a+1];
        if (b%2==1) res+=drzewoliniowek[b-1];
        a>>=1;
        b>>=1;
    }
    return res;
}
void updateminmaks(int n, treepair v) {
    n+=1<<(MJ-1);
    drzewominmaksow[n]={v.first,{v.second,-(n-(1<<(MJ-1)))}};
    n>>=1;
    while (n>0) {
        drzewominmaksow[n].first=max(drzewominmaksow[2*n].first,drzewominmaksow[2*n+1].first);
        drzewominmaksow[n].second=min(drzewominmaksow[2*n].second,drzewominmaksow[2*n+1].second);
        n>>=1;
    }
}
treepairext readminmaks(int a, int b) {
    a+=1<<(MJ-1);b+=1<<(MJ-1);
    treepairext res = drzewominmaksow[a];
    res.first = max(res.first,drzewominmaksow[b].first);
    res.second = min(res.second,drzewominmaksow[b].second);
    while ((a>>1)!=(b>>1)) {
        if (a%2==0) {
            res.first = max(res.first,drzewominmaksow[a+1].first);
            res.second = min(res.second,drzewominmaksow[a+1].second);
        }
        if (b%2==1) {
            res.first = max(res.first,drzewominmaksow[b-1].first);
            res.second = min(res.second,drzewominmaksow[b-1].second);
        }
        a>>=1;
        b>>=1;
    }
    res.second.second = -res.second.second;
    return res;
}
void compdarray(long long *array, int begin, bool compjp=false, int inc=1) {
    deque<pair<int,long long>> kolejkamon;
    for (int i=0;i<N;i++) updateminmaks(i,{0,INF});
    for (int i=begin;i>0&&i<=n;i+=inc) {
        auto besto = readminmaks(0,cost[i]-(compjp?0:1));
        long long best = besto.first;
        if (inc<0) best = besto.second.first;
        jp[i][0]=n+1;
        sjp[i][0]=(prefdist[n+1]-prefdist[i])*cost[i];
        if (best==0 || best==INF) array[i]=INF;
        else {
            array[i]=abs(prefdist[i]-prefdist[best]);
            jp[i][0]=best;
            sjp[i][0]=abs(prefdist[i]-prefdist[best])*cost[i];
        }
        updateminmaks(cost[i],{i,i});
    }
    for (int i=0;i<N;i++) updateminmaks(i,{0,INF});
}
int main() {
    scanf("%d %d",&n,&q);
    dist.resize(n+2);cost.resize(n+2); prefdist.resize(n+2);
    for (int i=1;i<=n;i++) scanf("%lld",&dist[i]);
    for (int i=1;i<=n;i++) scanf("%lld",&cost[i]);
    cost[0]=1e18;
    for (int i=2;i<=n+1;i++) prefdist[i]=prefdist[i-1]+dist[i-1];

    vector<zapytanie> zapytania(q);
    for (int i=0;i<q;i++) scanf("%d %d %lld",&zapytania[i].a,&zapytania[i].b,&zapytania[i].u);
    for (int i=0;i<q;i++) zapytania[i].indeks=i;
    sort(zapytania.begin(),zapytania.end());
    compdarray(dl, 1);
    compdarray(dr,n,true,-1);
    for (int i=1;i<=n;i++) updateminmaks(i,{dist[i],cost[i]});
    jp[n+1][0]=n+1;
    // updateminmaks(n+1,{0,0});
    for (int i=n+1;i>0;i--) {
        for (int j=1;j<MJ;j++) {
            jp[i][j]=jp[jp[i][j-1]][j-1];
            sjp[i][j]=sjp[i][j-1]+sjp[jp[i][j-1]][j-1];
        }
    }
    vector<przejscie> przejscia;
    for (int i=1;i<=n;i++) {
        przejscia.push_back({0,i,0,{cost[i],0}});
        przejscia.push_back({min(dl[i],dr[i]),i,1,{0,min(dl[i],dr[i])*cost[i]}});
        przejscia.push_back({dl[i]+dr[i]-min(dl[i],dr[i]),i,2,{-cost[i],(dl[i]+dr[i])*cost[i]}});
        przejscia.push_back({dl[i]+dr[i],i,3,{0,0}});
    }
    sort(przejscia.begin(),przejscia.end());
    int przejsciapointer=0;
    vector<long long> odpowiedz(q);
    for (auto x:zapytania) {
        while (przejsciapointer<przejscia.size() && przejscia[przejsciapointer].warunek<=x.u) {
            updatelin(przejscia[przejsciapointer].indeks,przejscia[przejsciapointer].v);
            przejsciapointer++;
        }
        if (readminmaks(x.a,x.b-1).first > x.u) {
            odpowiedz[x.indeks]=-1;
            continue;
        }
        long long maksbeg = prefdist[x.a]+x.u, maksend = prefdist[x.b]-x.u;
        auto itb = upper_bound(prefdist.begin(),prefdist.end(),maksbeg), ite = lower_bound(prefdist.begin(),prefdist.end(),maksend);
        itb--;
        int granicaleft = min((int)(itb-prefdist.begin()),x.b), granicaright = max(x.a, (int)(ite-prefdist.begin()));
        int l = x.a;
        long long wyn=0;
        for (int i=MJ-1;i>=0;i--)
            if (jp[l][i]<=granicaleft) {
                wyn+=sjp[l][i];
                l=jp[l][i];
            }
        if (l!=x.b) {
            wyn+=min(x.u,min(dr[l],prefdist[x.b]-prefdist[l]))*cost[l];
            l++;
        }
        auto mini = readminmaks(max(granicaright,l),x.b).second;
        auto liniowe = readlin(l,mini.second-1);

        // wyn+=(prefdist[min(l+1,x.b)]-prefdist[l])*cost[l];
        wyn+=liniowe.a*x.u + liniowe.b;
        if (l!=x.b) {
            wyn+=(prefdist[x.b]-prefdist[mini.second])*mini.first;
            if (mini.second != x.b) {
                if (dl[mini.second] <= prefdist[mini.second]-prefdist[x.a] && true)
                    wyn -= min(prefdist[x.b]-prefdist[mini.second],max(0ll,x.u-dl[mini.second]))*mini.first;
            }
        }
        odpowiedz[x.indeks]=wyn;
    }
    for (int i=0;i<q;i++) printf("%lld\n",odpowiedz[i]);
    return 0;
}

컴파일 시 표준 에러 (stderr) 메시지

Main.cpp: In function 'int main()':
Main.cpp:125:10: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  125 |     scanf("%d %d",&n,&q);
      |     ~~~~~^~~~~~~~~~~~~~~
Main.cpp:127:33: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  127 |     for (int i=1;i<=n;i++) scanf("%lld",&dist[i]);
      |                            ~~~~~^~~~~~~~~~~~~~~~~
Main.cpp:128:33: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  128 |     for (int i=1;i<=n;i++) scanf("%lld",&cost[i]);
      |                            ~~~~~^~~~~~~~~~~~~~~~~
Main.cpp:133:32: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  133 |     for (int i=0;i<q;i++) scanf("%d %d %lld",&zapytania[i].a,&zapytania[i].b,&zapytania[i].u);
      |                           ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...