제출 #1330597

#제출 시각아이디문제언어결과실행 시간메모리
1330597Zbyszek99Tower (JOI24_tower)C++20
100 / 100
649 ms109040 KiB
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
#define ll long long
#define ld long double
#define ull unsigned long long
#define ff first
#define ss second
#define pii pair<int,int>
#define pll pair<long long, long long>
#define vi vector<int>
#define vl vector<long long>
#define pb push_back
#define rep(i, b) for(int i = 0; i < (b); ++i)
#define rep2(i,a,b) for(int i = a; i <= (b); ++i)
#define rep3(i,a,b,c) for(int i = a; i <= (b); i+=c)
#define count_bits(x) __builtin_popcountll((x))
#define all(x) (x).begin(),(x).end()
#define siz(x) (int)(x).size()
#define forall(it,x) for(auto& it:(x))
using namespace __gnu_pbds;
using namespace std;
typedef tree<int, null_type, less<int>, rb_tree_tag,tree_order_statistics_node_update> ordered_set;
//mt19937 mt;void random_start(){mt.seed(chrono::time_point_cast<chrono::milliseconds>(chrono::high_resolution_clock::now()).time_since_epoch().count());}
//ll los(ll a, ll b) {return a + (mt() % (b-a+1));}
const ll INF = 1e18+50;
const ll INF_L = 1e18+40;
const ll MOD = 1e9+7;

struct seg_dp
{
    ll l,r,val;
    bool operator<(const seg_dp& other) const 
    {
        if(r != other.r) return r<other.r;
        return l<other.l;
    }
};
struct comp
{
    bool operator()(pll a, pll b) const
    {
        if(a.ss != b.ss) return a.ss < b.ss;
        return a.ff < b.ff;
    }
};

ll D,A,B;
int n,q;
set<seg_dp> dp;
set<pll,comp> non_seg;
ll total_add = 0;
unordered_map<ll,vector<pll>> block_segs;
unordered_map<ll,vector<pll>> queries;
set<ll> blocks;
ll query_ans[200001];

ll get_val(ll x)
{
    auto it = dp.lower_bound({-1,x,-1});
    if(it == dp.end() || (*it).l > x) return INF;
    return (*it).val + A*(x-(*it).l);
}

void split_by_poz(ll p)
{
    auto it = dp.lower_bound({-1,p,-1});
    if(it == dp.end() || (*it).l > p) return;
    ll val = (*it).val + (p-(*it).l+1);
    ll val2 = (*it).val;
    ll l = (*it).l;
    ll r = (*it).r;
    dp.erase(it);
    if(l != p) dp.insert({l,p-1,val2});
    dp.insert({p,r,val});
}

int main()
{
    ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    //random_start();
    cin >> n >> q >> D >> A >> B;
    ll min_ = D-1;
    rep(i,n)
    {
        ll l,r;
        cin >> l >> r;
        min_ = min(min_,l-1);
        r = min(l+D-1,r);
        blocks.insert(l/D);
        blocks.insert(l/D);
        blocks.insert(l/D+1);
        blocks.insert(l/D+2);
        block_segs[l/D].pb({l%D,min(D-1,l%D+(r-l))});
        if(l/D != r/D) block_segs[r/D].pb({0,r%D});
    }
    rep(qq,q)
    {
        ll x;
        cin >> x;
        blocks.insert(x/D);
        query_ans[qq] = -1;
        if(x/D != 0) queries[x/D].pb({x%D,qq});
        else
        {
            if(x <= min_) query_ans[qq] = A*x;
        }
    }
    dp.insert({0,min_,0});
    if(min_ != D-1) non_seg.insert({min_+1,D-1});
    ll prev_seg = 0;
    vector<pll> ok_segs;
    vector<pll> del_segs2;
    vector<pll> add_seg;
    vector<pll> can_better;
    forall(b,blocks)
    {
        if(b == 0) continue;
        total_add += (b-1-prev_seg)*min(A*D,B);
        prev_seg = b;
        ok_segs = {};
        add_seg = {};
        can_better = {};
        ll cur = 0;
        forall(it,block_segs[b])
        {
            if(it.ff-1 >= cur) ok_segs.pb({cur,it.ff-1});
            cur = it.ss+1;
        }
        if(cur != D) ok_segs.pb({cur,D-1});
        bool is_zero = 0;
        if(siz(ok_segs) != 0 && ok_segs[0].ff == 0)
        {
            ll zero = get_val(D-1);
            if(zero != INF)
            {
                is_zero = 1;
                can_better.pb({0,zero+A-B});
            }
        }
        total_add += B;
        forall(it,ok_segs)
        {
            del_segs2 = {};
            auto s = non_seg.upper_bound({-1,it.ff});
            while(s != non_seg.end() && (*s).ff <= it.ss)
            {
                del_segs2.pb({max(it.ff,(*s).ff),min(it.ss,(*s).ss)});
                s++;
            }
            forall(s,del_segs2)
            {
                if(s.ff == it.ff) continue;
                ll val = get_val(s.ff-1);
                if(val == INF || s.ff == it.ff) continue;
                dp.insert({s.ff,s.ss,val+A});
                if(s.ss != it.ss) can_better.pb({s.ss+1,val+A*(s.ss-s.ff+2)});
            }
            ll l = it.ff;
            ll r = it.ss;
            if(siz(del_segs2) > 0 && (it.ff != 0 || !is_zero) && del_segs2[0].ff == it.ff) l = del_segs2[0].ss+1;
            if(l <= r) add_seg.pb({l,r});
        }
        non_seg = {};
        cur = 0;
        forall(it,add_seg)
        {
            if(it.ff != cur) non_seg.insert({cur,it.ff-1});
            cur = it.ss+1; 
        }
        if(cur != D) non_seg.insert({cur,D-1});
        forall(non,non_seg)
        {
            while(true)
            {
                auto s = dp.lower_bound({-1,non.ff,-1});
                if(s == dp.end() || (*s).l > non.ss) break;
                seg_dp s2 = *s;
                dp.erase(s);
                if(s2.l < non.ff) dp.insert({s2.l,non.ff-1,s2.val});
                if(s2.r > non.ss) dp.insert({non.ss+1,s2.r,s2.val+A*(non.ss+1-s2.l)});
            }
        }
        forall(it,can_better)
        {
            if(get_val(it.ff) <= it.ss) continue;
            split_by_poz(it.ff);
            ll r2 = D-1;
            auto nxt = non_seg.lower_bound({-1,it.ff});
            if(nxt != non_seg.end()) r2 = (*nxt).ff-1;
            ll r = it.ff;
            auto cur_seg = dp.lower_bound({-1,it.ff,-1});
            while(cur_seg != dp.end() && (*cur_seg).r <= r2)
            {
                if((*cur_seg).val <  it.ss + A*((*cur_seg).l-it.ff))
                {
                    r = (*cur_seg).l-1;
                    break;
                }
                else
                {
                    dp.erase(cur_seg);
                    cur_seg = dp.lower_bound({-1,it.ff,-1});
                }
            }
            if(cur_seg == dp.end() || (*cur_seg).r > r2) r = r2;
            dp.insert({it.ff,r,it.ss});
        }
        forall(it,queries[b]) query_ans[it.ss] = get_val(it.ff)+total_add;
    }
    rep(qq,q) if(query_ans[qq] < INF) cout << query_ans[qq] << "\n"; else cout << "-1\n";
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...