제출 #300030

#제출 시각아이디문제언어결과실행 시간메모리
300030MarcoMeijer커다란 상품 (IOI17_prize)C++14
0 / 100
20 ms8688 KiB
#include "prize.h"
#include <bits/stdc++.h>

using namespace std;

#define REP(a,b,c) for(int a=int(b); a<int(c); a++)
#define REV(a,b,c) for(int a=int(c-1); a>=int(b); a--)
#define RE(a,b) REP(a,0,b)
#define FOR(a,b) for(auto& a:b)
#define pb push_back
#define fi first
#define se second
#define all(a) a.begin(), a.end()

typedef long long ll;
typedef pair<int,int> ii;
typedef vector<int> vi;
typedef vector<ii> vii;

const int INF=1e9;
const int MX=1e5;

map<int, vi> mem;
map<int, map<int, set<int>>> bst;
int sm;
int n;
vi LB;

int SEG[MX*4], LAZY[MX*4];

void buildSeg(int p=0, int l=0, int r=n-1) {
    SEG[p] = n-1;
    LAZY[p] = n-1;
    if(l == r) return;
    int m=(l+r)/2;
    buildSeg(p*2+1,l,m);
    buildSeg(p*2+2,m+1,r);
}
void setSeg(int i, int j, int v, int lazy=n-1, int p=0, int l=0, int r=n-1) {
    if(j > i) return;
    SEG [p] = min(SEG [p], lazy);
    LAZY[p] = min(LAZY[p], lazy);
    if(j < l || i > r) return;
    if(i <= l && j >= r) {
        SEG [p] = min(SEG [p], v);
        LAZY[p] = min(LAZY[p], v);
        return;
    }
    int m = (l+r)/2;
    setSeg(i,j,v,LAZY[p],p*2+1,l,m);
    setSeg(i,j,v,LAZY[p],p*2+2,m+1,r);
    SEG [p] = min(SEG[p*2+1], SEG[p*2+2]);
    LAZY[p] = n-1;
}
int getSeg(int i, int lazy=n-1, int p=0, int l=0, int r=n-1) {
    SEG [p] = min(SEG [p], lazy);
    LAZY[p] = min(LAZY[p], lazy);
    if(i < l || i > r) return INF;
    if(l == r) return SEG[p];
    int m = (l+r)/2;
    int a = getSeg(i,LAZY[p],p*2+1,l,m);
    int b = getSeg(i,LAZY[p],p*2+2,m+1,r);
    LAZY[p] = n-1;
    return min(a,b);
}

vi Ask(int i) {
    if(mem.count(i)) return mem[i];
    vi ret = ask(i);
    if(ret[0]+ret[1] == sm) {
        setSeg(0,ret[0]-1,i-1);
    }
    return mem[i] = ret;
}


int find_best(int N) {
    n = N;
    int sq = ceil(sqrt(n))+2;
    int mn = min(sq*2+2, n);

    sm = 0;
    RE(i,mn) {
        vi res = Ask(i);
        sm = max(sm, res[0]+res[1]);
    }

    vi g; g.assign(n,-1);
    vi J;
    RE(i,n) J.pb(i);
    buildSeg();
    RE(i,sm) {
        if(g[i] != -1) continue;

        int lb=0, ub=getSeg(i);
        if(i) lb=g[i-1]+1;

        while(lb != ub) {
            int mid=(lb+ub+1)/2;
            vi res = Ask(mid);
            if(res[0] + res[1] == sm) {
                if(res[0] > i) ub=mid-1;
                else lb=mid+1;
                if(lb == ub) g[i] = lb;
            } else {
                int j = J[mid];
                vi update;
                while(1) {
                    res = Ask(j);
                    if(res[0] + res[1] == sm) {
                        if(res[0] == i) {
                            lb = ub = j+1;
                        }
                        break;
                    }
                    update.pb(j);
                    if(j == 0) {
                        lb = ub = 0;
                        break;
                    }
                    j = J[j-1];
                }
                FOR(k,update) J[k] = j;
                if(lb == ub) {
                    REP(k,lb,mid+1) {
                        g[i+k-lb] = k;
                    }
                    if(mid == n-1) break;
                    res = Ask(++mid);
                    while(res[0]+res[1] != sm) {
                        g[i+mid-lb] = mid;
                        if(mid == n-1) break;
                        res = Ask(++mid);
                    }
                } else {
                    res = Ask(j);    
                    if(res[0] > i) ub=j-1;
                    else lb=mid+1;
                    if(lb == ub) g[i] = lb;
                }
            }
        }

        vi res = Ask(g[i]);
        if(res[0]+res[1] == 0) return g[i];
    }
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...