题目链接
给定一个整数 m,对于任意一个整数集合 S,定义“校验值”如下:
从集合 S 中取出 m 对数(即 2*M 个数,不能重复使用集合中的数,如果 S 中的整 数不够 m 对,则取到不能取为止),使得“每对数的差的平方”之和最大,这个最大值 就称为集合 S 的“校验值”。现在给定一个长度为 n 的数列 A 以及一个整数 k。我们要把 A 分成若干段,使得 每一段的“校验值”都不超过 k。求最少需要分成几段。#includeusing namespace std;#define maxn 600005#define LL long longint a[maxn],b[maxn],c[maxn];int n,m;LL k;void mem(int l,int mid,int r){ int i=l,j=mid+1,zz=r,ii=l; while(i<=mid&&j<=r){ if(b[i] k) return 0; else return 1;}bool work(int l,int r,int rr){ for(int j=rr+1;j<=r;j++) b[j]=a[j]; // 每次只用在b后面加上我们后来倍增的一段区间 sort(b+rr+1,b+r+1); // 把增加的一段排序 后面可以用归并 if(xxx(l,rr,r)) return 1; return 0;}int main(){ int t; cin>>t; while(t--){ scanf("%d%d%lld",&n,&m,&k); for(int j=1;j<=n;j++){ scanf("%d",&a[j]); } int ans=0; int l=1,p=1,r=l; b[1]=a[1]; while(l<=n){ if((r+p)<=n&&work(l,r+p,r)){ for(int i=l;i<=r+p;i++) b[i]=c[i]; //把每次符合的序列按顺序放在b里面 r+=p; p*=2; }else p/=2; if(p==0){ l=r+1; r=l; p=1; ans++; } } cout< <