P14917 [GESP202512 五级] 数字移动

题目描述

小 A 有一个包含 NNN 个正整数的序列 A={A1,A2,⋯ ,AN}A=\{A_1,A_2,\cdots,A_N\}A={A1,A2,,AN},序列 AAA 恰好包含 N2\frac{N}{2}2N 对不同的正整数。形式化地,对于任意 1≤i≤N1 \le i \le N1iN,存在唯一一个 jjj 满足 1≤j≤N,i≠j,Ai=Aj1\le j \le N, i\neq j, A_i=A_j1jN,i=j,Ai=Aj

小 A 希望每对相同的数字在序列中相邻,为了实现这一目的,小 A 每次操作会选择任意 i(1≤i≤N)i(1\le i\le N)i(1iN),将当前序列的第 iii 个数字移动到任意位置,并花费对应数字的体力。

例如,假设序列 A={1,2,1,3,2,3}A=\{1,2,1,3,2,3\}A={1,2,1,3,2,3},小 A 可以选择 i=2i=2i=2,将 A2=2A_2=2A2=2 移动到 A3=1A_3=1A3=1 的后面,此时序列变为 {1,1,2,3,2,3}\{1,1,2,3,2,3\}{1,1,2,3,2,3},耗费 222 点体力。小 A 也可以选择 i=3i=3i=3,将 A3=1A_3=1A3=1 移动到 A2=2A_2=2A2=2 的前面,此时序列变为 {1,1,2,3,2,3}\{1,1,2,3,2,3\}{1,1,2,3,2,3},花费 111 点体力。

小 A 可以执行任意次操作,但他希望自己每次花费的体力尽可能小。小 A 希望你能帮他计算出一个最小的 xxx,使得他能够在每次花费的体力均不超过 xxx 的情况下令每对相同的数字在序列中相邻。

输入格式

第一行一个正整数 NNN,代表序列长度,保证 NNN 为偶数。

第二行包含 NNN 个正整数 A1,A2,…,ANA_1,A_2,\ldots,A_NA1,A2,,AN,代表序列 AAA。且对于任意 1≤i≤N1\le i\le N1iN,存在唯一一个 jjj 满足 1≤j≤N,i≠j,Ai=Aj1\le j\le N,i\neq j,A_i=A_j1jN,i=j,Ai=Aj

数据保证小 A 至少需要执行一次操作。

输出格式

输出一行,代表满足要求的 xxx 的最小值。

输入输出样例 #1

输入 #1

6
1 2 1 3 2 3

输出 #1

2

说明/提示

对于 40%40\%40% 的测试点,保证 1≤N,Ai≤1001\le N,A_i\le 1001N,Ai100

对于所有测试点,保证 1≤N,Ai≤1051\le N,A_i\le 10^51N,Ai105

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;	// 严格要求 (将long long 类型取别名)
ll a[1000100], b[1000100];
bool func(ll n, ll mid){
	memset(b, 0, sizeof(b));
	ll t = 1;
	for(ll i = 1; i <= n; i++){
		if(a[i] > mid){
			b[t++] = a[i];
		}
	}
	
	for(ll i = 1; i <= t - 1; i += 2){	//已经确保i不会访问到最后的元素 
		if(b[i] != b[i + 1]){
			return false;
		}
	}
	return true;
} 
int main(){
	ios :: sync_with_stdio(0);	// 提高cin、cout的运行速度
	cin.tie(0);
	cout.tie(0);
	
	ll n, maxn = -1e9;
	cin >> n;
	
	for(ll i = 1; i <= n; i++){
		cin >> a[i];
		maxn = max(maxn, a[i]);	//输入的最大值 等一会二分要用 
	}
	
	ll l = 1, r = maxn;
	
	while(l < r){
		ll mid = (l + r) / 2;
		if(func(n, mid)){	//如果符合x要求可能就大了 
			r = mid;
		}
		else{	//否则x就可能要求小了 
			l = mid + 1;
		}
	}
	cout << l << endl;	//最后l == r 

    return 0;
}


Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐