D. Range and Partition

Posted thusloop

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了D. Range and Partition相关的知识,希望对你有一定的参考价值。

D. Range and Partition
题意:给你一个长为n的数组,让你分成k段,满足每段在[x,y]内的严格大于在在[x,y]外的,请你最小化y − x并输出切割方案。
思路:若有cnt1个数在[x,y]内 cnt2个数在[x,y]外 则整个区间一定能分成cnt1-cnt2段(类似中位数分段:传送门
cnt1+cnt2=n , cnt1-cnt2=k 则cnt1=(n+k+1)/2
可以用双指针求出 [x,y] 内有cnt1个数的最小区间

//#pragma GCC optimize(2)
//#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
#define int long long
#define fi first
#define se second
#define pb push_back
#define pii pair<int,int>
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
const int inf=8e18;
const int maxn=2e5+100;
int a[maxn],cnt[maxn];
signed main()

	IOS
	int tt;
	cin>>tt;
	while(tt--)
	
		int n,k;
		cin>>n>>k;
		for(int i=1;i<=n;i++)
		
			cin>>a[i];
			cnt[a[i]]++;
		
		int cnt1=(n+k+1)/2,l=1,r=n,mn=n,now=0;
		for(int i=1,j=1;i<=n;i++)
		
			while(j<=n&&now<cnt1) 
			
				now+=cnt[j];
				j++;
			
			if(now<cnt1)break;
			if(j-i<mn)
			
				mn=j-i;
				l=i;
				r=j-1;
			
			now-=cnt[i];
		
		cout<<l<<" "<<r<<"\\n";
		now=0;
		int i,j;
		for(i=1,j=1;i<=n;i=j)
		
			if(k==1)break;
			now=0;
			while(j<=n&&now<1)
			
				if(a[j]>=l&&a[j]<=r)now++;
				else now--;
				j++;
			
			cout<<i<<" "<<j-1<<"\\n";
			k--;
		
		cout<<j<<" "<<n<<"\\n";
		for(int i=1;i<=n;i++) cnt[i]=0;
	


以上是关于D. Range and Partition的主要内容,如果未能解决你的问题,请参考以下文章

D. The Fair Nut and the Best Path

Codeforces Round #737 (Div. 2) D. Ezzat and Grid 线段树模拟最长上升子序列

D. Tree and Queries

Codeforces 437 D. The Child and Zoo 并查集

D. Vasya and Arrays

CF 547 D. Mike and Fish