hihocoeder1384

hihocoeder1384

算法竞赛进阶指南上的题目

我们肯定是吧最大值和最小值匹配,次大值和次小值匹配以此类推

首先,类似于区间覆盖的思想,我们对于一个(L),找到最大的满足条件的(R)

之后把(R + 1)作为下一个(L)继续这个操作

现在,问题转化成了我们如何寻找最大的(R)

一个比较明显的思路就是去二分,但是二分时间复杂度不对

因为如果每次只能前进一格,二分时间复杂度就变成了(n^2log{n})

考虑倍增的思想

我们对于每个(L)

初始设置(R= L - 1,p = 1)

之后求加上([R + 1,R + p])时候合法

合法的话 (p = p imes 2)

否则 (p = p / 2)

每次暴力判断新加入的区间是否合法

可以证明这样时间复杂度

(nlog^2{n})

之后发现,对于新加进来的区间,我们只需要把它排序,然后和原有的区间进行归并即可

时间复杂度就变成了(nlog n)

#include<cstdio>
#include<iostream>
#include<queue>
#include<algorithm>
#include<cstring>
#include<cctype>
#include<vector>
#include<ctime>
#include<cmath>
#define LL long long
#define pii pair<int,int>
#define mk make_pair
#define fi first
#define se second
#define min std::min
#define max std::max
const int N = 5e5 + 3;
int a[N];
int n,m;LL k;
std::vector <int> A,B,G;
inline LL read(){
	LL v = 0,c = 1;char ch = getchar();
	while(!isdigit(ch)){
		if(ch == '-') c = -1;
		ch = getchar();
	}
	while(isdigit(ch)){
		v = v * 10 + ch - 48;
		ch = getchar();
	}
	return v * c;
}
inline bool check(int l,int r){
	B.clear(),G.clear();
	for(int i = l;i <= r;++i) B.push_back(a[i]);
	sort(B.begin(),B.end());
	int now1 = 0;int now2 = 0;
	while(now1 < A.size() && now2 < B.size()){
		if(A[now1] < B[now2]) G.push_back(A[now1++]);
		else G.push_back(B[now2++]);
	}
	while(now1 < A.size()) G.push_back(A[now1++]);
	while(now2 < B.size()) G.push_back(B[now2++]);
	LL res = 0;
	now1 = 0,now2 = G.size() - 1;
	for(int cnt = 0;cnt < m && now1 < now2;now1++,now2--,cnt++) res += 1ll * (G[now1] - G[now2]) * (G[now1] - G[now2]); 
	if(res <= k){
		A = G;
		return 1;
	}
	else return 0;
}
int main(){
	//	freopen("A.in","r",stdin);
//	freopen("A1.out","w",stdout);
	int T = read();
	while(T--){
		int ans = 0;
		n = read(),m = read(),k = read();
		for(int i = 1;i <= n;++i) a[i] = read();
		int l = 1,r = 0;
		while(l <= n){
			int p = 1;
			A.clear();
			while(p){
				int t = min(n,r + p);
				if(check(r + 1,t)){
					r = t;
					if(t == n) break;	
					p <<= 1;
				}
				else p >>= 1;
			}
			l = r + 1;
			ans++;
		}
		printf("%d
",ans);
	}
	return 0;
}
/*
1
10 2 10
4 1 3 2 1 3 2 1 3 4 


*/

原文地址:https://www.cnblogs.com/wyxdrqc/p/11633954.html