样例输入
3
3 2
1 2 3
1 2
3 2
1 2 3
-1 -2
3 3
-4 3 1
4 2 1
样例输出
0
3
3
解题思路:排序+前缀和+二分查找
因为数组b是可以插入到数组a任意位置,要想k最大,就要尽可能把b的小数插到a数组的前面。所以,用qsort方法对数组b进行排序。
每次都要考虑前缀和,那么我们求出数组a和数组b的前缀和,存入原数组中。这样就只需要考虑当前位的值。
循环遍历a数组,从b数组中找到最接近-a[i]-1的数并且不能大于-a[i]-1,x+a[i]=-1,所以查找-a[i]-1。找最接近的是为了让k尽可能大。假设t为从b数组中找到最接近-a[i]-1的数的下标,如果a[i]+b[t]<0,则i+t即为符号题意的前i+t个数。如果i+t>k,更新k的值。
举个例子:下标从1开始
A:-4 3 1 更新后A:-4 -1 0
B:1 2 4 更新后B:1 3 7
数组a要查找的x:3 0 -1
i=1,从数组b找到最接近x=3的下标值为2,即t=2。此时i+t=3,更新k的值为3
i=2,从数组b找到最接近x=0,在数组b中找不到<=0的数,t=0,不插入b的数,a2=-1<0满足,此时i+t=2,不更新k的值。
i=3,从数组b找到最接近x=0,在数组b中找不到<=-1的数。a3=0不满足小于0。
所以k=3。
#include<stdio.h>
#include<stdlib.h>
int a[1005]={},b[1005]={};
//从小到大排序
int cmp(const void *a,const void *b){
return *(int*)a-*(int*)b;
}
int n,m;
//二分查找数组b最接近x的数
int find(int x){
int mid,res=0,left=1,right=m;
while(left<=right){
mid=(left+right)/2;
if(b[mid]<=x){
res=mid;
left=mid+1;
}else{
right=mid-1;
}
}
return res;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
int i;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(i=1;i<=m;i++){
scanf("%d",&b[i]);
}
//数组b从小到大排序
qsort(b+1,m,sizeof(int),cmp);
//求前缀和
for(i=2;i<=n;i++)a[i]+=a[i-1];
for(i=2;i<=m;i++)b[i]+=b[i-1];
int k=0,t;
for(i=0;i<=n;i++){
//x+a[i]=-1,所以查找-a[i]-1
t=find(-a[i]-1);
if(a[i]+b[t]<0&&i+t>k)k=i+t;
}
printf("%d\n",k);
}
}