Submission #538991

#TimeUsernameProblemLanguageResultExecution timeMemory
53899179brue던전 (IOI21_dungeons)C++17
63 / 100
7186 ms1380216 KiB
#include "dungeons.h"
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int LIM = 25;

int n;
ll arr[400002], power[400002];
int w[400002], l[400002];

ll nxt[LIM][60002][LIM]; /// 계속 지기만 했을 때의 최종 위치
ll sum[LIM][60002][LIM]; /// 계속 지기만 했을 때의 체력 변화
ll lim[LIM][60002][LIM]; /// 계속 지기만 할 수 있기 위한 최초 체력의 최댓값
ll bonus[400002];

void init(int N, vector<int> s, vector<int> p, vector<int> W, vector<int> L){
	n = N;
	for(int i=0; i<n; i++) arr[i] = s[i];
	for(int i=0; i<n; i++) power[i] = p[i], w[i]=W[i], l[i]=L[i];
	l[n]=w[n]=n;
	arr[n] = 1e18, power[n]=1e18;

    for(int f=0; f<LIM; f++){
        for(int i=0; i<=n; i++){
            if((1<<f) <= arr[i]){
                nxt[f][i][0] = l[i];
                sum[f][i][0] = power[i];
                lim[f][i][0] = arr[i]-1;
            }
            else{
                nxt[f][i][0] = w[i];
                sum[f][i][0] = arr[i];
                lim[f][i][0] = 1e18;
            }
        }
        for(int d=1; d<LIM; d++){
            for(int i=0; i<=n; i++){
                nxt[f][i][d] = nxt[f][nxt[f][i][d-1]][d-1];
                sum[f][i][d] = sum[f][i][d-1] + sum[f][nxt[f][i][d-1]][d-1];
                sum[f][i][d] = min(sum[f][i][d], ll(1e18));
                lim[f][i][d] = min(lim[f][i][d-1], lim[f][nxt[f][i][d-1]][d-1] - sum[f][i][d-1]);
            }
        }
    }

    for(int i=n-1; i>=0; i--){
        bonus[i] = arr[i] + bonus[w[i]];
    }
}

ll simulate(int x, int _z){
    ll z = _z;
    for(int f=0; f<LIM; f++){
        if((1<<(f+1)) <= z || x==n) continue;

        /// 1. 계속 지다가 결국 탈출하기
        int tx = x, cnt1 = 0;
        ll tz = z;
        for(int d=LIM-1; d>=0; d--){
            if(tz + sum[f][tx][d] < (1<<(f+1))){
                tz += sum[f][tx][d];
                tx = nxt[f][tx][d];
                cnt1 += (1<<d);
            }
        }

        /// 2. 이겨서 탈출하기
        int cnt2 = 0;
        tx = x;
        tz = z;
        for(int d=LIM-1; d>=0; d--){
            if(lim[f][tx][d] >= tz){
                tz += sum[f][tx][d];
                tx = nxt[f][tx][d];
                cnt2 += (1<<d);
            }
        }

        int cnt = min(cnt1, cnt2);
        for(int d=0; d<LIM; d++){
            if((cnt>>d)&1){
                z += sum[f][x][d];
                x = nxt[f][x][d];
            }
        }

        if(x==n) break;

        assert(z < (1<<(f+1)));
        if(z >= arr[x]) z += arr[x], x = w[x];
        else z += power[x], x = l[x];
        assert(z >= (1<<(f+1)));
    }

    return z + bonus[x];
}
#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...