제출 #392180

#제출 시각아이디문제언어결과실행 시간메모리
392180limabeansRoad Construction (JOI21_road_construction)C++17
100 / 100
3249 ms924900 KiB
#include <bits/stdc++.h>
using namespace std;

template<typename T>
void out(T x) { cout << x << endl; exit(0); }
#define watch(x) cout << (#x) << " is " << (x) << endl





using ll = long long;


const int maxn = 1e6 + 5;
const ll inf = 1e18;

struct psegtree {
    pair<ll,int> pr; //(xyval, idx)
    psegtree *left;
    psegtree *right;

    psegtree() : pr(inf, -1), left(), right() {}

    static psegtree init(int dep) {
	if (dep==0) {
	    return {};
	} else {
	    psegtree *ch = new psegtree(init(dep-1));
	    return {ch, ch};
	}
    }


    psegtree(psegtree *l, psegtree *r) {
	left = l;
	right = r;
	pr = min(l->pr, r->pr);
    }

    psegtree upd(int v, int tl, int tr, int i, ll val) {
	//cout<<tl<<","<<tr<<": "<<left<<" "<<right<<endl;
	
	if (tl==tr) {
	    psegtree res;
	    res.pr = {val, i};
	    return res;
	} else {
	    int tm=(tl+tr)/2;
	    if (i<=tm) {
		return {new psegtree(left->upd(2*v,tl,tm,i,val)), right};
	    } else {
		return {left, new psegtree(right->upd(2*v+1,tm+1,tr,i,val))};
	    }
	}
    }

    pair<ll,int> qryMin(int v, int tl, int tr, int l, int r) {
	if (l>tr || r<tl) {
	    return {inf, -1};
	} else if (l<=tl && tr<=r) {
	    return pr;
	} else {
	    int tm=(tl+tr)/2;
	    return min(left->qryMin(2*v,tl,tm,l,r), right->qryMin(2*v+1,tm+1,tr,l,r));
	}
    }
};

struct pt {
    ll x,y;
};

int n, k;
pt a[maxn];

psegtree U[maxn], D[maxn];



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


    cin>>n>>k;
    for (int i=0; i<n; i++) {
	cin>>a[i].x>>a[i].y;
    }


    sort(a,a+n, [&](pt p, pt q) {
	return p.x<q.x;
    });
    

    vector<pair<ll,int>> ord;
    ord.push_back({-inf,-1}); // (y,i)
    for (int i=0; i<n; i++) {
	ord.push_back({a[i].y,i});
    }

    sort(ord.begin(), ord.end());
    int N = (int)ord.size() - 1;

    auto get = [&](ll y, int i) {
	return lower_bound(ord.begin(), ord.end(), make_pair(y,i)) - ord.begin();
    };

    U[0] = psegtree::init(19);
    D[0] = psegtree::init(19);


    // sort pts by x
    // each psegtree to the left contains active pts with lower x
    // within the psegtree, stuff is sorted by y, with value being (-x+y)



    
    for (int i=0; i<n; i++) {
	int loc = get(a[i].y, i);
	U[i+1] = U[i].upd(1,1,N,loc,-a[i].x+a[i].y);
	D[i+1] = D[i].upd(1,1,N,loc,-a[i].x-a[i].y);
    }


    priority_queue<pair<ll,int>,vector<pair<ll,int>>,greater<pair<ll,int>>> pq; // (ans, idx)



    // i is 0-indexed
    auto push = [&](int i) {
	ll x = a[i].x;
	ll y = a[i].y;
	int loc = get(y, i);
	pair<ll,int> ures = U[i+1].qryMin(1,1,N,loc+1,N);
	pair<ll,int> dres = D[i+1].qryMin(1,1,N,1,loc-1);

	if (ures.first == inf && dres.first == inf) {
	    return;
	}
	if (ures.first+x-y < dres.first+x+y) {
	    pq.push({ures.first+x-y, i});
	    U[i+1] = U[i+1].upd(1,1,N,ures.second, inf);
	} else {
	    pq.push({dres.first+x+y, i});
	    D[i+1] = D[i+1].upd(1,1,N,dres.second, inf);
	}
    };



    
    for (int i=0; i<n; i++) {
	push(i);
    }


    for (int it=0; it<k; it++) {
	auto cur = pq.top();
	pq.pop();
	cout<<cur.first<<"\n";
	push(cur.second);
    }
    
    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...