Submission #1329371

#TimeUsernameProblemLanguageResultExecution timeMemory
1329371Zbyszek99Bitaro the Brave 3 (JOI25_brave3)C++20
100 / 100
1058 ms9812 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 int INF = 1e9+50;
const ll INF_L = 1e18+40;
const ll MOD = 1e9+7;

struct elm
{
    ll time,cnt,P;
    bool operator<(const elm& other) const
    {
        return time < other.time;
    }
};

struct line
{
    ll a,b;
    bool operator<(const line& other) const
    {
        return a < other.a;
    }
    ll operator()(ll x)
    {
        return a*x+b;
    }
};

int n;
ll L,T;
vector<elm> elms;
vector<pair<ll,line>> events;
line L_line[6002];
ll max_D[6002];
int nxt[6002];
vector<line> hull;

void D_bor(int l, int r, ll bor)
{
    ll sum1 = 0;
    ll sum2 = 0;
    int nxt2 = r+1;
    for(int i = r; i >= l; i--)
    {
        if(elms[i].P >= bor) nxt[i] = nxt2;
        if(elms[i].P >= bor) nxt2 = i;
    }
    rep2(i,l,r)
    {
        if(elms[i].P < bor) continue;
        sum1 += elms[i].cnt;
        sum2 += elms[nxt[i]].time-elms[i].time;
        L_line[i] = {-sum1,sum2};
    }
    hull = {{0,0}};
    rep2(i,l,r)
    {
        max_D[i] = -1;
        if(elms[i].P < bor) continue;
        max_D[i] = min(L,(elms[nxt[i]].time-elms[i].time)/elms[i].cnt);
        while(siz(hull) >= 2) 
        {
            if(hull.back().a != L_line[i].a) 
            {
                ld c1 = (ld)(L_line[i].b-hull.back().b)/(ld)(hull.back().a-L_line[i].a);
                ld c2 = (ld)(L_line[i].b-hull[siz(hull)-2].b)/(ld)(hull[siz(hull)-2].a-L_line[i].a);
                max_D[i] = min(max_D[i],(ll)c1);
                max_D[i] = min(max_D[i],(ll)c2);
                if(c1 >= c2) hull.pop_back();
                else break;
            }
            else hull.pop_back();
        }
        if(hull.back().a == L_line[i].a) hull.pop_back();
        if(siz(hull) > 0) max_D[i] = min(max_D[i],(L_line[i].b-hull.back().b)/(hull.back().a-L_line[i].a));
        hull.pb(L_line[i]);
        if(max_D[i] == 0 || (i != r && L_line[i].a == L_line[i+1].a)) max_D[i] = -1;
    }
}

vector<pair<ll,line>> my_func;
vector<pair<ll,line>> my_func2;
vector<pair<ll,line>> merge_ans;

void merge_func()
{
    line cur = {my_func[0].ss.a+my_func2[0].ss.a,my_func[0].ss.b+my_func2[0].ss.b};
    merge_ans = {{0,cur}};
    int p1 = 0;
    int p2 = 0;
    while(p1 < siz(my_func)-1 || p2 < siz(my_func2)-1)
    {
        if(p2 == siz(my_func2)-1 || (p1 != siz(my_func)-1 && my_func[p1+1].ff < my_func2[p2+1].ff))
        {
            cur.a -= my_func[p1].ss.a;
            cur.b -= my_func[p1].ss.b;
            p1++;
            cur.a += my_func[p1].ss.a;
            cur.b += my_func[p1].ss.b;
            merge_ans.pb({my_func[p1].ff,cur});
        }
        else if(p1 == siz(my_func)-1 || (p2 != siz(my_func2)-1 && my_func2[p2+1].ff < my_func[p1+1].ff))
        {
            cur.a -= my_func2[p2].ss.a;
            cur.b -= my_func2[p2].ss.b;
            p2++;
            cur.a += my_func2[p2].ss.a;
            cur.b += my_func2[p2].ss.b;
            merge_ans.pb({my_func2[p2].ff,cur});
        }
        else
        {
            cur.a -= my_func[p1].ss.a;
            cur.b -= my_func[p1].ss.b;
            p1++;
            cur.a += my_func[p1].ss.a;
            cur.b += my_func[p1].ss.b;
            cur.a -= my_func2[p2].ss.a;
            cur.b -= my_func2[p2].ss.b;
            p2++;
            cur.a += my_func2[p2].ss.a;
            cur.b += my_func2[p2].ss.b;
            merge_ans.pb({my_func2[p2].ff,cur});
        }
    }
    my_func = merge_ans;
}

void solve_elm(int v)
{
    D_bor(1,v-1,elms[v].P);
    D_bor(v,n,elms[v].P+1);
    my_func = {};
    my_func2 = {};
    ll pop = -1;
    ll cnt = 0;
    int last = v;
    for(int i = v-1; i >= 1; i--)
    {
        if(max_D[i] > pop)
        {
            if(cnt != 0) my_func.pb({pop+1,{cnt,-(elms[v].time-elms[nxt[i]].time)}});
            else my_func.pb({pop+1,{0,0}});
            pop = max_D[i];
        }
        if(elms[i].P >= elms[v].P) 
        {
            cnt += elms[i].cnt;
            last = i;
        }
    }
    if(pop != L && last != v) my_func.pb({pop+1,{cnt,-(elms[v].time-elms[last].time)}});
    else if(last == v) my_func.pb({0,{0,0}});
    pop = -1;
    cnt = 0;
    last = n+1;
    for(int i = n; i >= v; i--) if(elms[i].P >= elms[v].P+1) cnt += elms[i].cnt;
    int cnt2 = cnt;
    for(int i = n; i >= v; i--)
    {
        if(max_D[i] > pop)
        {
            if(cnt != cnt2) my_func2.pb({pop+1,{cnt,T-elms[nxt[i]].time}});
            else my_func2.pb({pop+1,{cnt,0}});
            pop = max_D[i];
        }
        if(elms[i].P >= elms[v].P+1) 
        {
            cnt -= elms[i].cnt;
            last = i;
        }
    }
    if(pop != L && last != n+1) my_func2.pb({pop+1,{cnt,T-elms[last].time}});
    else if(last == n+1) my_func2.pb({0,{0,0}});
    merge_func();
    forall(it,my_func)
    {
        it.ss.a += elms[v].cnt;
        it.ss.b += -(T-elms[v].time);
    }
    line prev_ = {0,0};
    ll first_time = -1;
    rep(i,siz(my_func))
    {
        ll nxt = (i != siz(my_func)-1 ? my_func[i+1].ff-1 : L);
        if(my_func[i].ss(nxt) <= 0) continue;
        ll zero = max(my_func[i].ff,(ll)ceil((ld)(-my_func[i].ss.b)/(ld)(my_func[i].ss.a)));
        my_func[i].ss.a *= elms[v].P;
        my_func[i].ss.b *= elms[v].P;
        events.pb({zero,{-prev_.a+my_func[i].ss.a,-prev_.b+my_func[i].ss.b}});
        prev_ = my_func[i].ss;
        my_func[i].ss.a /= elms[v].P;
        my_func[i].ss.b /= elms[v].P;
        if(my_func[i].ss(nxt) > nxt*elms[v].cnt)
        {
            if(my_func[i].ss.a == elms[v].cnt) first_time = my_func[i].ff;
            else first_time = max(my_func[i].ff,(ll)ceil((ld)(-my_func[i].ss.b)/(ld)(my_func[i].ss.a-elms[v].cnt)));
            break;
        }
    }
    if(first_time != -1) events.pb({first_time,{-prev_.a+elms[v].cnt*elms[v].P,-prev_.b}});
}

int main()
{
    ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    //random_start();
    cin >> n >> L >> T;
    elms.pb({-1,0,0});
    rep(i,n)
    {
        ll time,cnt,P;
        cin >> time >> cnt >> P;
        elms.pb({time,cnt,P});
    }
    sort(all(elms));
    elms.pb({T,-1,-1});
    rep2(i,1,n) solve_elm(i);
    sort(all(events));
    line cur = {0,0};
    vector<pair<int,line>> func = {};
    ll max_ok = L;
    if(siz(events) == 0 || events[0].ff != 0) func.pb({0,{0,0}});
    if(siz(events) != 0) max_ok = max(0LL,events[0].ff-1);
    rep(i,siz(events))
    {
        cur.a = cur.a+events[i].ss.a;
        cur.b = cur.b+events[i].ss.b;
        if(i == siz(events)-1 || events[i].ff != events[i+1].ff) func.pb({events[i].ff,cur});
    }
    int q;
    cin >> q;
    rep(qq,q)
    {
        ll x;
        cin >> x;
        int l = 0;
        int r = siz(func)-1;
        int ans = -1;
        while(l <= r)
        {
            int mid = (l+r)/2;
            if(func[mid].ss(func[mid].ff) <= x)
            {
                l = mid+1;
                ans = mid;
            }
            else
            {
                r = mid-1;
            }
        }
        if(ans == -1) cout << "0\n";
        else
        {
            if(func[ans].ss.a != 0) cout << min((x-func[ans].ss.b)/func[ans].ss.a,(ans != siz(func)-1 ? func[ans+1].ff-1 : L)) << "\n";
            else 
            {
                if(func[ans].ss.b <= x) cout << (ans != siz(func)-1 ? func[ans+1].ff-1 : L) << "\n";
                else cout << max_ok << "\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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...