求助站外题卡常
  • 板块学术版
  • 楼主Graygoo
  • 当前回复9
  • 已保存回复9
  • 发布时间2022/3/30 14:08
  • 上次更新2023/10/28 05:11:00
查看原帖
求助站外题卡常
535714
Graygoo楼主2022/3/30 14:08

题目描述

一个序列的极差定义为此序列中最大值和最小值之差。给你一个长度为n的序列a_1..an,你需要选出k个极差均不小于X且长度为L(L>=1)的不同连续子序列。a{i1},...a{i1+L-1}, a{i2},...a{i2+L-1}, ... , a{ik},...a_{ik+L-1}, (i1..ik)互不相同。

要求能满足条件的最大的X,在满足X最大的情况下,再让L最小

输入格式:第一行一个整数T,表示测试数据组数

每组数据中:第一行两个整数n,k;第二行n个整数a_1,a_2,...,a_n

100%的数据,1<=T<=10, 1<=k<=n<=100000, -1e9<=a<=1e9

蒟蒻写了一个二分答案,答案内尺取+单调队列+差分,复杂度应该是O(log(1e9) n t),但是只过了70分。

大佬们,有没有复杂度更优秀的做法?如果没有能不能帮我优化一下常数?

70分的代码:

#include<bits/stdc++.h>
using namespace std;
long long ai[110001];
int n;
int k;
long long cf[110001];
int ok(long long x){
	memset(cf,0,sizeof(cf));
	int ptr=0;
	static int d[200001];
	static int d2[200001];
	int lr=1,rr=0;
	int lr1=1,rr1=0;
	for(int i=1;i<=n;i++){
		if(ptr<i){
			ptr=i;
			while(lr<=rr and ai[d[rr]]<= ai[i])rr--;
			d[++rr]=i;
			while(lr1<=rr1 and ai[d2[rr1]]>= ai[i])rr1--;
			d2[++rr1]=i;
		}
		while(ptr <=n and ai[d[lr]]-ai[d2[lr1]] < x){
			ptr++;
			while(lr<=rr and ai[d[rr]]<= ai[ptr])rr--;
			d[++rr]=ptr;
			while(lr1<=rr1 and ai[d2[rr1]]>= ai[ptr])rr1--;
			d2[++rr1]=ptr;
		}
		cf[ptr-i+1]++,cf[n-i+2]--;
		while(lr<=rr and d[lr]<=i)lr++;
		while(lr1<=rr1 and d2[lr1]<=i)lr1++;
	}
	int sm=0;
	for(int i=1;i<=n;i++){
		sm+=cf[i];
		if(sm>=k)return i;
	}
	return -1;
}
inline int read()
{
	int s=0,w=1;
	char ch=getchar();
	while(!isdigit(ch))
	{
		if(ch=='-') w=-1;
		ch=getchar();
	}
	while(isdigit(ch)) 
	{
		s=s*10+ch-'0',ch=getchar();
	}
	return s*w;
}
int main(){
	freopen("select.in","r",stdin);
	freopen("select.out","w",stdout);
	int t;
	cin>>t;
	for(int j=1;j<=t;j++){
		//clock_t ss,ee;
		//ss=clock();
		cin>>n>>k;
        long long minn=9999999999,maxx=-9999999999;
		for(int i=1;i<=n;i++)ai[i]=read(),minn=min(minn,ai[i]),maxx=max(maxx,ai[i]);
		long long l=0,r=maxx-minn;
		long long ans=0,res=0,ans2=0;
		while(l<=r){
			long long mid=(l+r)>>1;
			res=ok(mid);	
			//cout<<mid<<endl;
			if(res==-1)r=mid-1;
			else l=mid+1,ans=res,ans2=mid;
		}
		cout<<ans2<<" "<<ans<<endl;
		//ee=clock();
	//	cout<<(double)(ee-ss)/CLOCKS_PER_SEC;
	}
	return 0;
}
2022/3/30 14:08
加载中...