Submission #1297326

#TimeUsernameProblemLanguageResultExecution timeMemory
1297326Zbyszek99Bodyguard (JOI21_bodyguard)C++20
100 / 100
13607 ms1479436 KiB
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#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 line
{
    ll a,b;
    bool is = 1;
    ll operator()(ll x)
    {
        if(is == 0) return -5e18;
        return a*x+b;
    }
};

struct lichao
{
    ll l = -((1LL << 32LL));
    ll r = (1LL << 32LL)-1;
    line best = {(ll)-1e18-2137,(ll)-1e18,0};
    lichao* left = NULL;
    lichao* right = NULL;
    void add_line(line line)
    {
        if(best.is == 0) 
        {
            best = line;
            return;
        }
        ll mid = (l+r)/2;
        if(line(mid) > best(mid)) swap(best,line);
        if(l == r) return;
        if(line.a < best.a)
        {
            if(left == NULL)
            {
                left = new lichao;
                left -> l = l;
                left -> r = mid-1;
            }
            if(left -> l <= left -> r)
            {
                left -> add_line(line);
            }
        }
        else
        {
            if(right == NULL)
            {
                right = new lichao;
                right -> l = mid+1;
                right -> r = r;
            }
            if(right -> l <= right -> r)
            {
                right -> add_line(line);
            }
        }
    }
    ll get_val(ll x)
    {
        if(x <= (l+r)/2) return max((ll)best(x),(left != NULL ? left -> get_val(x) : (ll)-3e18));
        else return max((ll)best(x),(right != NULL ? right -> get_val(x) : (ll)-3e18));
    }
};

struct seg
{
    pll p1,p2;
    ll c;
    bool t;
};

struct event
{
    ll x,y,type,ind;
    bool operator<(const event& other)
    {
        if(y != other.y) return y > other.y;
        return type < other.type;
    }
};

pll rotate(ll t, ll p)
{
    return {t+p,t-p};
}


vector<seg> segs;
vector<int> segs_p[2801];
vector<pll> points;
ll dist[24000000];
ll query_ans[3000001];
vector<pll> graph[24000001];
vi graph2[20000001];
int cur_p = 0;
vector<pair<pll,int>> queries;
int cur_line[2801];
int n,q;

void solve2(vector<pair<pll,int>>& q2,vi& s)
{
    sort(all(q2));
    reverse(all(q2));
    lichao tree_;
    int cur = 0;
    forall(it,q2)
    {
        while(cur < siz(s) && segs[s[cur]].p1.ff >= it.ff.ff)
        {
            if(cur_line[s[cur]] != siz(segs_p[s[cur]])) 
            {
                tree_.add_line({-(cur_line[s[cur]] != 0 ? segs[s[cur]].c : 0),dist[segs_p[s[cur]][cur_line[s[cur]]]]+(cur_line[s[cur]] != 0 ? segs[s[cur]].c : 0)*points[segs_p[s[cur]][cur_line[s[cur]]]].ss});
            }
            cur++;
        }
        query_ans[it.ss] = max(query_ans[it.ss],tree_.get_val(it.ff.ss));
    }
}

void solve()
{
    rep(i,n) cur_line[i] = siz(segs_p[i]);
    vector<event> events;
    vector<pair<pll,int>> q2;
    vector<pii> vs;
    rep(i,n) if(segs[i].t) vs.pb({segs[i].p1.ff,i});
    sort(all(vs));
    reverse(all(vs));
    vi s;
    rep(i,siz(vs)) s.pb(vs[i].ss);
    rep(i,n)
    {
        if(segs[i].t)
        {
            forall(it,segs_p[i]) events.pb({points[it].ff,points[it].ss,0,i});
        }
    }
    forall(it,queries) events.pb({it.ff.ff,it.ff.ss,1,it.ss});
    sort(all(events));
    forall(it,events)
    {
        if(it.type == 0)
        {
            solve2(q2,s);
            q2 = {};
            cur_line[it.ind]--;
        }
        else
        {
            q2.pb({{it.x,it.y},it.ind});
        }
    }
    solve2(q2,s);
}

int main()
{
    ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    //random_start();
    cin >> n >> q;
    rep(i,n)
    {
        ll t,a,b,c;
        cin >> t >> a >> b >> c;
        segs.pb({rotate(t,a),rotate(t+abs(a-b),b),c,a>b});
    }
    rep(i,n)
    {
        points.pb(segs[i].p1);
        segs_p[i].pb(cur_p++);
        points.pb(segs[i].p2);
        segs_p[i].pb(cur_p++);
    }
    rep(i,n)
    {
        rep(j,n)
        {
            if(segs[i].t == 0 && segs[j].t == 1)
            {
                if(segs[i].p1.ff <= segs[j].p1.ff && segs[i].p2.ff >= segs[j].p1.ff && segs[i].p1.ss <= segs[j].p2.ss && segs[i].p2.ss >= segs[j].p1.ss)
                {
                    points.pb({segs[j].p1.ff,segs[i].p1.ss});
                    segs_p[i].pb(cur_p);
                    segs_p[j].pb(cur_p++);
                }
            }
            if(segs[j].p1.ff >= segs[i].p1.ff && segs[j].p1.ss >= segs[i].p1.ss)
            {
                if(segs[i].t == 0)
                {
                    points.pb({min(segs[j].p1.ff,segs[i].p2.ff),segs[i].p1.ss});
                    graph2[cur_p].pb(j*2);
                    segs_p[i].pb(cur_p++);
                }
                else
                {
                    points.pb({segs[i].p2.ff,min(segs[i].p2.ss,segs[j].p1.ss)});
                    graph2[cur_p].pb(j*2);
                    segs_p[i].pb(cur_p++);
                }
            }
            if(segs[j].p2.ff >= segs[i].p2.ff && segs[j].p2.ss >= segs[i].p2.ss)
            {
                if(segs[j].t == 0)
                {
                    points.pb({max(segs[j].p1.ff,segs[i].p2.ff),segs[j].p1.ss});
                    graph2[i*2+1].pb(cur_p);
                    segs_p[j].pb(cur_p++);
                }
                else
                {
                    points.pb({segs[j].p1.ff,max(segs[j].p1.ss,segs[i].p2.ss)});
                    graph2[i*2+1].pb(cur_p);
                    segs_p[j].pb(cur_p++);
                }
            }
        }
    }
    vector<pair<pll,int>> vs;
    map<int,int> m;
    rep(i,siz(points)) vs.pb({points[i],i});
    sort(all(vs));
    int sp = siz(points);
    points = {};
    int cur = -1;
    pll pop = {-1e11,-1e11};
    forall(it,vs)
    {
        if(pop.ff != it.ff.ff || pop.ss != it.ff.ss)
        {
            cur++;
            points.pb(it.ff);
        }
        m[it.ss] = cur;
        pop = it.ff;
    }
    rep(i,sp)
    {
        forall(it,graph2[i])
        {
            graph[m[i]].pb({m[it],0});
        }
    }
    rep(i,n) forall(it,segs_p[i]) it = m[it];
    rep(i,n)
    {
        set<int> x;
        forall(it,segs_p[i]) x.insert(it);
        segs_p[i] = {};
        forall(it,x) segs_p[i].pb(it);
        int pop = -1;
        ll pop_poz = 0;
        forall(it,segs_p[i])
        {
            ll my_poz = points[it].ff;
            if(segs[i].t == 1) my_poz = points[it].ss;
            if(pop != -1) graph[pop].pb({it,(my_poz-pop_poz)*segs[i].c});
            pop = it;
            pop_poz = my_poz;
        }
    }
    for(int i = siz(points)-1; i >= 0; i--)
    {
        dist[i] = 0;
        forall(it,graph[i]) 
        {
            dist[i] = max(dist[i],it.ss+dist[it.ff]);
        }
    }
    rep(qq,q)
    {
        ll t,p;
        cin >> t >> p;
        queries.pb({rotate(t,p),qq});
    }
    solve();
    rep(i,siz(points)) swap(points[i].ff,points[i].ss);
    rep(i,q) swap(queries[i].ff.ff,queries[i].ff.ss);
    rep(i,n)
    {
        swap(segs[i].p1.ff,segs[i].p1.ss);
        swap(segs[i].p2.ff,segs[i].p2.ss);
        segs[i].t ^= 1;
    }
    solve();
    rep(qq,q) cout << query_ans[qq]/2 << "\n";
}

Compilation message (stderr)

bodyguard.cpp: In function 'void solve()':
bodyguard.cpp:177:35: warning: narrowing conversion of 'it.event::ind' from 'long long int' to 'int' [-Wnarrowing]
  177 |             q2.pb({{it.x,it.y},it.ind});
      |                                ~~~^~~
#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...