Submission #1030329

#TimeUsernameProblemLanguageResultExecution timeMemory
1030329hotboy2703Comparing Plants (IOI20_plants)C++17
100 / 100
1078 ms161956 KiB
#include "plants.h"
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
#define pll pair <ll,ll>
#define fi first
#define se second
#define MP make_pair
#define sz(a) (ll((a).size()))
#define BIT(mask,i) (((mask) >> (i))&1)
#define MASK(i) (1LL<<(i))
namespace trung{
    const ll MAXN = 2e5+100;
    const ll INF = 1e9+7;
    ll n,k;
    vector <int> val;
    namespace seg{
        pll tree[MAXN*4];
        ll lazy[MAXN*4];
        pll combine(pll x,pll y){
            if (x.fi > y.fi)return y;
            else return x;
        }
        void build(ll id=1,ll l=0,ll r=n-1){
            if (l==r){tree[id] = MP(val[l],l);}
            else{
                ll mid = (l + r) >> 1;
                build(id<<1,l,mid);
                build(id<<1|1,mid+1,r);
                tree[id] = combine(tree[id<<1],tree[id<<1|1]);
            }
        }
        void push(ll id,ll x){
            tree[id].fi+=x;
            lazy[id]+=x;
        }
        void lz(ll id){
            push(id<<1,lazy[id]);
            push(id<<1|1,lazy[id]);
            lazy[id] = 0;
        }
        void update(ll l1,ll r1,ll id=1,ll l=0,ll r=n-1){
//            if (id==1)cout<<"UPD "<<l1<<' '<<r1<<endl;
            if (l1 > r || l > r1 || l1 > r1)return;
            if (l1 <= l && r <= r1){
//                cout<<"UPD2 "<<l<<' '<<r<<endl;
                push(id,-1);
                return;
            }
            lz(id);
            ll mid = (l + r) >> 1;
            update(l1,r1,id<<1,l,mid);
            update(l1,r1,id<<1|1,mid+1,r);
            tree[id] = combine(tree[id<<1],tree[id<<1|1]);
        }
        void del(ll i,ll id=1,ll l=0,ll r=n-1){
            if (l > i || i > r)return;
            if (l==r){
//                cout<<"BRUH "<<i<<endl;
                tree[id].fi = INF;
                return;
            }
            lz(id);
            ll mid = (l + r) >> 1;
            del(i,id<<1,l,mid);
            del(i,id<<1|1,mid+1,r);
            tree[id] = combine(tree[id<<1],tree[id<<1|1]);
        }
        ll get(ll l1,ll r1,ll id=1,ll l=0,ll r=n-1){
            if (l1 > r || l > r1 || l1 > r1)return n+1;
            if (tree[id].fi!=0)return n+1;
            if (l1 <= l && r <= r1)return tree[id].se;
            lz(id);
            ll mid = (l + r) >> 1;
            ll res = get(l1,r1,id<<1,l,mid);
            if (res==n+1)res = get(l1,r1,id<<1|1,mid+1,r);
            return res;
        }
        ll sus(ll i,ll id=1,ll l=0,ll r=n-1){
            if (i > r || l > i)return INF+1;
            if (l == r)return tree[id].fi;
            lz(id);
            ll mid = (l + r) >> 1;
            return min(sus(i,id<<1,l,mid),sus(i,id<<1|1,mid+1,r));
        }
    }
    vector <ll> h;
    ll label;
    bool in[MAXN];
    void solve(ll x){
//        assert(in[x] == 0);
//        in[x] = 1;
        ll l = x-k+1,r=x-1;
//        cout<<x<<' '<<l<<' '<<r<<endl;
        ll tmp;
        while ((tmp=seg::get(l,r)) != n+1){
            solve(tmp);
        }
        while ((tmp=seg::get(l+n,r+n)) != n+1){
//            cout<<x<<' '<<tmp<<endl;
            solve(tmp);
        }

        seg::del(x);
        h[x] = --label;
        seg::update(l,r);
        seg::update(l+n,r+n);
    }
    const ll MAXK = 20;
    ll sp_nxt[MAXK][MAXN*2];
    ll sp_pre[MAXK][MAXN*2];
    bool solve_nxt(ll x,ll y){
        for (ll j = MAXK-1;j>=0;j--){
            if (sp_nxt[j][x] <= y)x = sp_nxt[j][x];
        }
        return (y-x<k&&h[y]>=h[x]);
    }
    bool solve_pre(ll x,ll y){
        for (ll j = MAXK-1;j>=0;j--){
            if (sp_pre[j][x] >= y)x = sp_pre[j][x];
        }
        return (x-y<k&&h[y]>=h[x]);
    }
}

void init(int K, std::vector<int> r){
    using namespace trung;
    val = r;
    n=sz(r);
    h.resize(n);
    k=K;
    seg::build();
//    cout<<"OK"<<endl;
    ll cur;
    label = n;
    while ((cur=seg::get(0,n-1)) != n+1){
//        cout<<"CUR "<<cur<<endl;
        solve(cur);
    }
    for (ll i = 0;i < n;i ++){
        h.push_back(h[i]);
    }
    h.insert(h.begin(),INF);
    h.push_back(INF);
    {
        set <pll> s;
        for (ll i = 1;i <= k - 1;i ++){
            s.insert(MP(h[i],i));
        }
        for (ll i = 1;i <= 2 * n;i ++){
            s.erase(MP(h[i],i));
            if (i + k - 1 <= 2 * n)s.insert(MP(h[i+k-1],i+k-1));
            auto tmp = s.lower_bound(MP(h[i],i)); ;
            if (tmp != s.end())sp_nxt[0][i] = (*tmp).se;
            else sp_nxt[0][i] = i;
        }
        s.clear();
        for (ll i = 2*n;i>=2*n-k+2;i--)s.insert(MP(h[i],i));
        for (ll i = 2*n;i >= 1;i--){
            s.erase(MP(h[i],i));
            if (i - k + 1 >= 1)s.insert(MP(h[i - k + 1],i - k + 1));
            auto tmp = s.lower_bound(MP(h[i],i)); ;
            if (tmp != s.end())sp_pre[0][i] = (*tmp).se;
            else sp_pre[0][i] = i;
        }
//        for (ll i = 1;i <= 2 * n;i ++){
//            cout<<h[i]<<' ';
//        }
//        cout<<endl;
//        for (ll i = 1;i <= 2 * n;i ++){
//            cout<<sp_nxt[0][i]<<' ';
//        }
//        cout<<endl;
//        for (ll i = 1;i <= 2 * n;i ++){
//            cout<<sp_pre[0][i]<<' ';
//        }
//        cout<<endl;
    }
    for (ll j = 1;j<MAXK;j ++){
        for (ll i = 1;i <= 2 * n;i ++){
            sp_nxt[j][i] = sp_nxt[j-1][sp_nxt[j-1][i]];
            sp_pre[j][i] = sp_pre[j-1][sp_pre[j-1][i]];
        }
    }
}
int compare_plants(int x, int y){
    using namespace trung;
    x++,y++;
    if (h[x] > h[y]){
        if (solve_nxt(y,x+n)||solve_pre(y,x))return 1;
        else return 0;
    }
    else{
        if (solve_nxt(x,y)||solve_pre(x+n,y))return -1;
        else return 0;
    }
//    return (h[x] > h[y] ? 1 : -1);
}

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