Submission #945872

#TimeUsernameProblemLanguageResultExecution timeMemory
945872beepbeepsheepRoad Construction (JOI21_road_construction)C++17
100 / 100
5754 ms171480 KiB
#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define ii pair<ll,ll>
#define iii tuple<ll,ll,ll>

#ifndef DEBUG
#define cerr if (0) cerr
#define endl '\n'
#endif // DEBUG

const ll maxn=2e5+5e4+5;
const ll inf=1e15;
const ll mod=1e9+7;

ll n;
ll x[maxn],y[maxn];
ii ranges[maxn];
vector<ll> pos;
vector<ii> updates;
ll fen[maxn];
void upd(ll x, ll v){
    while (x<maxn){
        fen[x]+=v;
        x+=(x&-x);
    }
}
ll query(ll x){
    ll ans=0;
    while (x){
        ans+=fen[x];
        x-=(x&-x);
    }
    return ans;
}
ll query(ll x, ll y){
    return query(y)-query(x-1);
}
ll check(ll len){
    vector<tuple<ll,ll,ll>> queries;
    for (int i=1;i<=n;i++){
        queries.emplace_back(y[i]-len-1,i,-1);
        //exclusive
        queries.emplace_back(y[i]+len,i,1);
        //inclusive
        ranges[i].first=lower_bound(pos.begin(),pos.end(),x[i]-len)
                        -pos.begin();
        ranges[i].second=upper_bound(pos.begin(),pos.end(),x[i]+len)
                        -pos.begin()-1;
    }
    sort(queries.begin(),queries.end());
    ll ans=0,ptr=0;
    memset(fen,0,sizeof(fen));
    for (auto [a,b,c]:queries){
        while (ptr!=updates.size() &&
               updates[ptr].first<=a){
            upd(updates[ptr].second,1);
            ptr++;
        }
        ans+=c*(query(ranges[b].first,ranges[b].second));
    }
    return (ans-n)/2;
}
struct node{
    ll s,e,m;
    vector<ii> v;
    node *l,*r;
    node(ll _s, ll _e){
        s=_s,e=_e,m=(s+e)>>1;
        if (s!=e) l=new node(s,m),r=new node(m+1,e);
    }
    void upd(ll x, ii p){
        if (s==e){
            v.emplace_back(p);
            return;
        }
        if (x>m) r->upd(x,p);
        else l->upd(x,p);
    }
    void build(){
        if (s!=e){
            l->build(),r->build();
            for (auto u:l->v) v.emplace_back(u);
            for (auto u:r->v) v.emplace_back(u);
        }
        sort(v.begin(),v.end()); //remember to put y first
    }
    vector<ll> query(ll x, ll y, ll v1, ll v2, ii p){
        if (x<=s && e<=y){
            ll x1,y1;
            tie(y1,x1)=p;
            ll lb=lower_bound(v.begin(),v.end(),
                              make_pair(v1,-inf))-v.begin();
            ll ub=upper_bound(v.begin(),v.end(),
                              make_pair(v2,inf))-v.begin();
            vector<ll> out;
            for (int i=lb;i<ub;i++){
                ll x2,y2;
                tie(y2,x2)=v[i];
                if (x1==x2 && y1==y2) continue;
                out.emplace_back(max(abs(x1-x2),abs(y1-y2)));
            }
            return out;
        }
        if (x>m) return r->query(x,y,v1,v2,p);
        if (y<=m) return l->query(x,y,v1,v2,p);
        vector<ll> out1=l->query(x,y,v1,v2,p);
        vector<ll> out2=r->query(x,y,v1,v2,p);
        for (auto u:out1) out2.emplace_back(u);
        return out2;
    }
}*root;
ll flat[maxn];
vector<ll> out;
void solve(ll len){
    for (int i=1;i<=n;i++){
        ranges[i].first=lower_bound(pos.begin(),pos.end(),x[i]-len)
                        -pos.begin();
        ranges[i].second=upper_bound(pos.begin(),pos.end(),x[i]+len)
                        -pos.begin()-1;
    }
    root=new node(1,n);
    for (int i=1;i<=n;i++){
        root->upd(flat[i],make_pair(y[i],x[i]));
    }
    root->build();
    for (int i=1;i<=n;i++){
        ll l,r;
        tie(l,r)=ranges[i];
        vector<ll> roads=root->query(l,r,y[i]-len,
                                     y[i]+len,make_pair(y[i],x[i]));
        //left x, right x, bottom y, top y, central point
        for (auto u:roads) out.emplace_back(u);
    }
}
int main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    ll a,b,k;
    cin>>n>>k;
    for (int i=1;i<=n;i++){
        cin>>a>>b;
        x[i]=a+b,y[i]=a-b;
        pos.emplace_back(x[i]);
    }
    pos.emplace_back(-inf);
    sort(pos.begin(),pos.end());
    pos.erase(unique(pos.begin(),pos.end()),pos.end());
    for (int i=1;i<=n;i++){
        flat[i]=lower_bound(pos.begin(),pos.end(),x[i])
                -pos.begin();
        updates.emplace_back(y[i],flat[i]);
    }
    sort(updates.begin(),updates.end());
    ll l=1,r=4'000'000'005,m;
    while (l!=r-1){
        m=(l+r)>>1;
        if (check(m)>=k) r=m; //we need to reach r
        else l=m;
    }
    //find everything <=l
    solve(l);
    sort(out.begin(),out.end());
    while (out.size()<2*k) out.emplace_back(r);
    for (int i=0;i<out.size();i+=2) cout<<out[i]<<endl;
    return 0;
}

Compilation message (stderr)

road_construction.cpp: In function 'long long int check(long long int)':
road_construction.cpp:56:19: warning: comparison of integer expressions of different signedness: 'long long int' and 'std::vector<std::pair<long long int, long long int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   56 |         while (ptr!=updates.size() &&
      |                ~~~^~~~~~~~~~~~~~~~
road_construction.cpp: In function 'int main()':
road_construction.cpp:165:22: warning: comparison of integer expressions of different signedness: 'std::vector<long long int>::size_type' {aka 'long unsigned int'} and 'long long int' [-Wsign-compare]
  165 |     while (out.size()<2*k) out.emplace_back(r);
      |            ~~~~~~~~~~^~~~
road_construction.cpp:166:19: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<long long int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  166 |     for (int i=0;i<out.size();i+=2) cout<<out[i]<<endl;
      |                  ~^~~~~~~~~~~
#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...