给定一个长度为 n
的整数数组 nums
和一个二维数组 queries
,其中 queries[i] = [li, ri]
。
对于每个查询 queries[i]
:
- 在
nums
的下标范围[li, ri]
内选择一个下标 子集。 - 将选中的每个下标对应的元素值减 1。
零数组 是指所有元素都等于 0 的数组。
如果在按顺序处理所有查询后,可以将 nums
转换为 零数组 ,则返回 true
,否则返回 false
。
示例 1:
输入: nums = [1,0,1], queries = [[0,2]]
输出: true
解释:
- 对于 i = 0:
- 选择下标子集
[0, 2]
并将这些下标处的值减 1。 - 数组将变为
[0, 0, 0]
,这是一个零数组。
- 选择下标子集
示例 2:
输入: nums = [4,3,2,1], queries = [[1,3],[0,2]]
输出: false
解释:
- 对于 i = 0:
- 选择下标子集
[1, 2, 3]
并将这些下标处的值减 1。 - 数组将变为
[4, 2, 1, 0]
。
- 选择下标子集
- 对于 i = 1:
- 选择下标子集
[0, 1, 2]
并将这些下标处的值减 1。 - 数组将变为
[3, 1, 0, 0]
,这不是一个零数组。
- 选择下标子集
提示:
1 <= nums.length <= 10^5
0 <= nums[i] <= 10^5
1 <= queries.length <= 10^5
queries[i].length == 2
0 <= li <= ri < nums.length
分析:和 3355 零数组变换 I 的方法类似,使用差分数组 + 二分答案解决。如果前 k 个查询即可让数组变为 0 数组,则 k + 1 个查询也可以。因此可以二分答案,检查中点是否能满足条件。
int minZeroArray(int* nums, int numsSize, int** queries, int queriesSize, int* queriesColSize) {
int l=0,r=queriesSize,ans=-1;
int diff[numsSize+5];diff[0]=nums[0];
int flag=0;
if(nums[0]>0)flag=1;
for(int i=1;i<numsSize;++i)
{
diff[i]=nums[i]-nums[i-1];
if(nums[i]>0)flag=1;
}
if(!flag)return 0;
while(l<r)
{
int mid=(l+r)/2;
int temp[numsSize+5],cnt[numsSize+5];
for(int i=0;i<numsSize;++i)
temp[i]=diff[i],cnt[i]=nums[i];
for(int i=0;i<=mid;++i)
temp[queries[i][0]]-=queries[i][2],temp[queries[i][1]+1]+=queries[i][2];
cnt[0]=temp[0];
if(cnt[0]>0)
{
l=mid+1;continue;
}
int f=1;
for(int i=1;i<numsSize;++i)
{
cnt[i]=cnt[i-1]+temp[i];
if(cnt[i]>0)
{
l=mid+1;f=0;break;
}
}
// printf("l=%d r=%d mid=%d ans=%d f=%d\n",l,r,mid,ans,f);
if(f)ans=mid+1,r=mid;
}
return ans;
}