제출 #301340

#제출 시각아이디문제언어결과실행 시간메모리
301340lordofmont식물 비교 (IOI20_plants)C++14
100 / 100
1662 ms26668 KiB
#include "plants.h"
#include <bits/stdc++.h>
#define low(i) (i<<(__builtin_clz(i)-31+n_bits))-(1<<n_bits)
#define high(i) ((i+1)<<(__builtin_clz(i)-31+n_bits))-(1<<n_bits)-1
using namespace std;
vector<int> tallest;
vector<int> shortest;
int n_global;
const int n_bits=20;
const int inf = 1e9;
int arr[1<<(n_bits+1)];
int lazyadd[1<<(n_bits+1)];

struct segtree {
    segtree(){}
    void build(vector<int> v) {
        assert(v.size()<(1<<n_bits));
        for(int i=0; i<(1<<n_bits); i++) {
            arr[i+(1<<n_bits)] = (i<(int)v.size() ? v[i] : inf);
        }
        for(int i=(1<<n_bits)-1; i>=1; i--) {
            arr[i] = min(arr[2*i], arr[2*i+1]);
        }
        for(int i=0; i<(1<<(n_bits+1)); i++) {
            lazyadd[i] = 0;
        }
    }
    int value(int node) {
        arr[node] += lazyadd[node];
        if(node<(1<<n_bits)) {
            lazyadd[2*node] += lazyadd[node];
            lazyadd[2*node+1] += lazyadd[node];
        }
        lazyadd[node] = 0;
        return arr[node];
    }
    void update(int node, int left, int right, int change) {
        if(right>=high(node) && left<=low(node)) {
            lazyadd[node] += change;
        } else if(right<low(node) || left>high(node)) {
            return;
        } else {
            update(2*node, left, right, change);
            update(2*node+1, left, right, change);
            arr[node] = min(value(node*2), value(node*2+1));
        }
    }

    void decr(int left, int right) {
        update(1, left, right, -1);
    }

    int find_zero(int node) {
        if(value(node)!=0) {
            return -1;
        }
        if(node >= (1<<n_bits)) {
            return arr[node]==0 ? node-(1<<n_bits) : -1;
        }
        int x = find_zero(node*2);
        if(x!=-1) return x;
        return find_zero(node*2+1);
    }
};

// gives you the lexi smallest ordering given the doubled array r
vector<int> lexi_smallest(int k, vector<int> r) {
    segtree s;
    s.build(r);
    vector<int> ret;
    ret.resize(r.size());
    queue<int> stash;
    for(int i=0; i<(int)r.size(); i++) {
        int p = s.find_zero(1);
        while(p==-1) {
            s.decr(stash.front(), 2*n_global-1);
            p = s.find_zero(1);
            stash.pop();
        }
        ret[p] = i;
        s.update(1, p, p, 1e9);

        s.decr(max(0, p-k+1), p);
        if(p<k-1) {
            stash.push(p-k+1+2*n_global);
        }
    }
    return ret;
}
void init(int k, std::vector<int> r) {
    n_global = r.size();
    for(int i=0; i<n_global; i++) {
        r.push_back(r[i]);
    }
    tallest = lexi_smallest(k,r);
    for(int &i: r) i = k-1-i;
    shortest = lexi_smallest(k,r);
}

int compare_plants(int x, int y) {
    if(x>y) return -compare_plants(y,x);
    if(tallest[x]>tallest[y] || shortest[y]>shortest[x+n_global]) return -1;
    if(shortest[x]>shortest[y] || tallest[y]>tallest[x+n_global]) return 1;
	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...
#Verdict Execution timeMemoryGrader output
Fetching results...