Submission #1278028

#TimeUsernameProblemLanguageResultExecution timeMemory
1278028denislavRoad Construction (JOI21_road_construction)C++20
38 / 100
3825 ms1531012 KiB
# include <iostream>
# include <vector>
# include <algorithm>
# include <queue>
# include <tuple>
using namespace std;

const long long INF=(long long)4e9+11;
const int MAX=3e5+11,LOG=20;

int n,K;
pair<int,int> a[MAX];
int orderP[MAX];
int orderM[MAX];
int real_val[MAX*2];

int ct;
int roots[MAX][LOG];
int tree[MAX*LOG*LOG];
int lv[MAX*LOG*LOG];
int rv[MAX*LOG*LOG];

int update(int pos, int d, int v, int l=1, int r=n*2)
{
    if(l==r)
    {
        ct++;
        tree[ct]=tree[v]+d;
        return ct;
    }

    int mid=(l+r)/2;
    if(pos<=mid)
    {
        ct++;
        int v2=ct;
        lv[v2]=update(pos,d,lv[v],l,mid);
        rv[v2]=rv[v];
        tree[v2]=tree[lv[v2]]+tree[rv[v2]];
        return v2;
    }
    else
    {
        ct++;
        int v2=ct;
        lv[v2]=lv[v];
        rv[v2]=update(pos,d,rv[v],mid+1,r);
        tree[v2]=tree[lv[v2]]+tree[rv[v2]];
        return v2;
    }
}

long long walk(int k, int v, int l=1, int r=n*2)
{
    if(l==r) return real_val[l];

    int mid=(l+r)/2;
    if(tree[lv[v]]>=k) return walk(k,lv[v],l,mid);
    else return walk(k-tree[lv[v]],rv[v],mid+1,r);
}

int roots_under[MAX][LOG];
int cnt_under[MAX][LOG];
int roots_over[MAX][LOG];
int cnt_over[MAX][LOG];

void cdq(int l, int r, int level)
{
    if(l==r) return ;

    //cout<<"Enter:"<<l<<" "<<r<<" "<<level<<endl;

    int mid=(l+r)/2;
    vector<pair<int,int>> LS,RS;
    for(int i=l;i<=mid;i++) LS.push_back({a[i].second,i});
    for(int i=mid+1;i<=r;i++) RS.push_back({a[i].second,i});
    sort(LS.begin(),LS.end());
    sort(RS.begin(),RS.end());

    int under=0,over=0;
    for(int i=mid+1;i<=r;i++) over=update(orderP[i],1,over);
    int ptr=0;
    for(pair<int,int> PA: LS)
    {
        int id=PA.second;
        while(ptr<(int)RS.size() and a[id].second>RS[ptr].first)
        {
            under=update(orderM[RS[ptr].second],1,under);
            over=update(orderP[RS[ptr].second],-1,over);
            ptr++;
        }
        roots_under[id][level]=under;
        roots_over[id][level]=over;
    }

    //cout<<"Pass:"<<l<<" "<<r<<" "<<level<<endl;

    cdq(l,mid,level+1);
    cdq(mid+1,r,level+1);
}

tuple<long long,int,int> ans;

void dc(int l, int r, int level, int idx)
{
    if(l==r) return ;

    int mid=(l+r)/2;
    if(l<=mid)
    {
        if(cnt_under[idx][level]+1<=tree[roots_under[idx][level]])
            ans=min(ans,make_tuple(walk(cnt_under[idx][level]+1,roots_under[idx][level])+a[idx].second-a[idx].first,level,0));

        if(cnt_over[idx][level]+1<=tree[roots_over[idx][level]])
            ans=min(ans,make_tuple(walk(cnt_over[idx][level]+1,roots_over[idx][level])-a[idx].second-a[idx].first,level,1));
    }

    if(idx<=mid) dc(l,mid,level+1,idx);
    else dc(mid+1,r,level+1,idx);
}

long long get_best(int idx)
{
    ans={INF,INF,INF};
    dc(1,n,0,idx);

    long long sc;
    int level,type;
    tie(sc,level,type)=ans;
    if(sc==INF) return INF;

    if(type==0) cnt_under[idx][level]++;
    else cnt_over[idx][level]++;
    return sc;
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);

    cin>>n>>K;
    for(int i=1;i<=n;i++) cin>>a[i].first>>a[i].second;
    sort(a+1,a+n+1);
    vector<pair<int,int>> compr;
    for(int i=1;i<=n;i++)
    {
        compr.push_back({a[i].first+a[i].second,i});
        compr.push_back({a[i].first-a[i].second,-i});
    }
    sort(compr.begin(),compr.end());
    for(int i=0;i<n*2;i++)
    {
        int id=compr[i].second;
        if(id>0)
        {
            orderP[id]=i+1;
            real_val[i+1]=compr[i].first;
        }
        else
        {
            orderM[-id]=i+1;
            real_val[i+1]=compr[i].first;
        }
    }

    cdq(1,n,0);

    priority_queue<pair<long long,int>,vector<pair<long long,int>>,greater<pair<long long,int>>> pq;
    for(int i=1;i<=n;i++) pq.push({get_best(i),i});
    for(int tt=1;tt<=K;tt++)
    {
        long long sc;
        int idx;
        tie(sc,idx)=pq.top();
        pq.pop();

        cout<<sc<<"\n";
        pq.push({get_best(idx),idx});
    }

    return 0;
}



#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...