Submission #364733

#TimeUsernameProblemLanguageResultExecution timeMemory
364733rqi고대 책들 (IOI17_books)C++14
50 / 100
1617 ms1048580 KiB
#include "books.h"
#include <bits/stdc++.h>
using namespace std;

typedef vector<int> vi;
typedef long long ll;

#define sz(x) (int)(x).size()
#define pb push_back
#define bk back()

const int MOD = 1e9+7;

const int mx = 1000005;
vi p;
int s;
int cycL[mx]; //leftmost of a cycle
int cycR[mx]; //rightmost of a cycle

void popLRSingles(){
	int L = 0;
	for(int i = 0; i < s; i++){
		if(p[i] == i){
			L = i+1;
		}
		else{
			break;
		}
	}

	vi newp;
	for(int i = L; i < sz(p); i++){
		newp.pb(p[i]);
	}

	p = newp;
	s = s-L;

	while(true){
		if(sz(p)-1 == s) break;
		if(p[sz(p)-1] == sz(p)-1){
			p.pop_back();
		}
		else{
			break;
		}
	}
}

int curL, curR;

vi Lfrees, Rfrees;

void getFrees(){
	while(true){
		bool updated = false;

		while(sz(Lfrees)){
			int node = Lfrees.bk;
			if(node < curL) break;
			updated = true;
			Lfrees.pop_back();
			curL = min(curL, cycL[node]);
			curR = max(curR, cycR[node]);
		}

		while(sz(Rfrees)){
			int node = Rfrees.bk;
			if(node > curR) break;
			updated = true;
			Rfrees.pop_back();
			curL = min(curL, cycL[node]);
			curR = max(curR, cycR[node]);
		}

		if(!updated) break;
	}
}

long long minimum_walk(vi _p, int _s) {
	p = _p;
	s = _s;
	popLRSingles();
	int n = sz(p);

	for(int i = 0; i < n; i++){
		cycL[i] = MOD;
		cycR[i] = -1;
	}

	for(int i = 0; i < n; i++){
		if(cycR[i] == -1){
			int curnode = i;

			vi cycle_nodes;
			while(true){
				cycle_nodes.pb(curnode);
				curnode = p[curnode];
				if(curnode == i) break;
			}

			for(auto u: cycle_nodes){
				cycL[i] = min(cycL[i], u);
				cycR[i] = max(cycR[i], u);
			}

			for(auto u: cycle_nodes){
				cycL[u] = cycL[i];
				cycR[u] = cycR[i];
			}
		}
	}

	ll ans = 0;

	for(int i = 0; i < n; i++){
		ans+=abs(p[i]-i);
	}



	curL = s;
	curR = s;

	for(int i = 0; i <= s; i++){
		Lfrees.pb(i);
	}
	for(int i = n-1; i >= s; i--){
		Rfrees.pb(i);
	}
	getFrees();

	while(curL > 0 || curR < n-1){
		int prev_curL = curL;
		int prev_curR = curR;

		ll L_cost = 0;
		ll R_cost = 0;
		bool non_boost = false;

		for(int i = curL-1; i >= 0; i--){
			if(i+1 == curL){
				L_cost+=2;
				curL--;
			}

			curL = min(curL, cycL[i]);
			if(cycR[i] > prev_curR){
				//found non boost
				non_boost = true;
				break;
			}
		}

		for(int i = curR+1; i < n; i++){
			if(i-1 == curR){
				R_cost+=2;
				curR++;
			}

			curR = max(curR, cycR[i]);
			if(cycL[i] < prev_curL){
				non_boost = true;
				break;
			}
		}

		if(!non_boost){
			ans+=L_cost+R_cost;
		}
		else{
			ans+=min(L_cost, R_cost);
		}

		getFrees();
	}

	return ans;
}
#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...