제출 #364741

#제출 시각아이디문제언어결과실행 시간메모리
364741rqi고대 책들 (IOI17_books)C++14
100 / 100
276 ms26908 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]-L);
	}

	p = newp;
	s = s-L;

	// for(int i = 0; i < sz(p); i++){
	// 	cout << i << " " << p[i] << "\n";
	// }

	while(true){
		if(sz(p)-1 == s) break;
		if(p[sz(p)-1] == sz(p)-1){
			//cout << sz(p)-1 << "\n";
			p.pop_back();
		}
		else{
			break;
		}
	}
}

int curL, curR;

int Lfrees, Rfrees;

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

		while(Lfrees >= 0){
			
			cout.flush();
			int node = Lfrees;
			if(node < curL) break;
			updated = true;
			Lfrees--;
			curL = min(curL, cycL[node]);
			curR = max(curR, cycR[node]);
		}

		while(Rfrees < sz(p)){
			int node = Rfrees;
			if(node > curR) break;
			updated = true;
			Rfrees++;
			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;
			while(true){
				cycL[i] = min(cycL[i], curnode);
				cycR[i] = max(cycR[i], curnode);
				curnode = p[curnode];
				if(curnode == i) break;
			}

			while(true){
				cycL[curnode] = cycL[i];
				cycR[curnode] = cycR[i];
				curnode = p[curnode];
				if(curnode == i) break;
			}
		}
	}

	ll ans = 0;

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



	curL = s;
	curR = s;

	Lfrees = s;
	Rfrees = s;

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