Submission #137765

#TimeUsernameProblemLanguageResultExecution timeMemory
137765random0029Ancient Books (IOI17_books)C++14
50 / 100
2044 ms36400 KiB
// ItnoE
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1000006;
int n, M[N], A[N], MN[N * 2], MX[N * 2];
inline void Set(int i, int val)
{
	i += n;
	MN[i] = MX[i] = val;
	for (; i; i >>= 1)
	{
		MN[i >> 1] = min(MN[i], MN[i ^ 1]);
		MX[i >> 1] = max(MX[i], MX[i ^ 1]);
	}
}
inline pair < int , int > Get(int l, int r)
{
	r ++;
	l += n; r += n;
	pair < int , int > ret = {INT_MAX, INT_MIN};
	for (; l < r; l >>= 1, r >>= 1)
	{
		if (l & 1)
		{
			ret.first = min(ret.first, MN[l]);
			ret.second = max(ret.second, MX[l]);
			l ++;
		}
		if (r & 1)
		{
			r --;
			ret.first = min(ret.first, MN[r]);
			ret.second = max(ret.second, MX[r]);
		}
	}
	return (ret);
}
int64_t minimum_walk(vector < int > P, int st)
{
	n = (int)P.size();
	ll SM = 0;
	for (int i = 0; i < n; i ++)
		SM += abs(P[i] - i), Set(i, P[i]);
	vector < pair < int , int > > cyc;
	for (int i = 0; i < n; i ++)
		if (!M[i] && P[i] != i)
		{
			int v = i;
			int Mx = -N * 2, Mn = N * 2;
			while (!M[v])
			{
				M[v] = 1;
				Mn = min(Mn, v);
				Mx = max(Mx, v);
				v = P[v];
			}
			A[Mn] = max(A[Mn], Mx);
			cyc.push_back({Mn, Mx});
		}
	if (SM == 0)
		return (SM);
	//bool fail = 1;
	int Mx = 0, last = -1;
	vector < pair < int , int > > vec;
	for (int i = 0; i < n; i ++)
	{
		Mx = max({Mx, A[i], i});
		if (P[i] != i && last == -1)
			last = i;
		if (P[i] == i)
			continue;
		if (Mx == i)
			vec.push_back({last, Mx}), last = -1;
		//if (i <= st && st <= Mx)
			//fail = 0;
	}
	if (P[st] == st)
	{
		int le = st, ri = st;
		while (le >= 0 && P[le] == le)
			le --;
		while (ri < n && P[ri] == ri)
			ri ++;
		if (le == -1) le = st;
		if (ri == n) ri = st;
		SM += (ri - le) * 2;
	}
	else
	{
		pair < int , int > X;
		for (auto Y : vec)
			if (Y.first <= st && st <= Y.second)
				X = Y;
		int le = st, ri = st;
		int tole = st, tori = st, cnt = 0;
		while (le > X.first || ri < X.second && cnt <= 2000)
		{
          cnt ++;
			while (1)
			{
				auto ff = Get(le, ri);
				if (ff.first >= le && ff.second <= ri)
					break;
				le = min(ff.first, le);
				ri = max(ff.second, ri);
			}
			tole = le;
			tori = ri;
			if (X.first == le && X.second == ri)
				break;
			while (tole >= X.first && P[tole] == tole)
				tole --;
			while (tori <= X.second && P[tori] == tori)
				tori ++;
			SM += (le - tole) * 2;
			SM += (tori - ri) * 2;
			le = tole;
			ri = tori;
		}
	}
	/*if (st != 0 && P[st] != st)
	{
		pair < int , int > X;
		for (auto Y : vec)
			if (Y.first <= st && st <= Y.second)
				X = Y;
		SM += min(st - X.first, X.second - st) * 2;
	}*/
	for (int i = 1; i < (int)vec.size(); i ++)
	{
		SM += (vec[i].first - vec[i - 1].second) * 2;
		assert(vec[i].first > vec[i - 1].second);
	}
	return (SM);
}

Compilation message (stderr)

books.cpp: In function 'int64_t minimum_walk(std::vector<int>, int)':
books.cpp:97:40: warning: suggest parentheses around '&&' within '||' [-Wparentheses]
   while (le > X.first || ri < X.second && cnt <= 2000)
                          ~~~~~~~~~~~~~~^~~~~~~~~~~~~~
#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...