力扣 第 169 场双周赛(A~D)

A:3736. 最小操作次数使数组元素相等 III
签到题。

1 class Solution:
2     def minMoves(self, nums: List[int]) -> int:
3         return max(nums)*len(nums)-sum(nums)

B:3737. 统计主要元素子数组数目 I

数据范围小,枚举左端点和右端点就能过,注意这里有一个技巧,我之前这种都是写三重循环的。

但是其实可以枚举左端点之后,从左端点扫到尾,然后右端点从右往左枚举,同时维护一下外层循环的数据。

 1 class Solution:
 2     def countMajoritySubarrays(self, nums: List[int], target: int) -> int:
 3         n=len(nums)
 4         res=0
 5         for i in range(n):
 6             cnt=Counter(nums[:i+1])
 7             for j in range(i+1):
 8                 if cnt[target]>(i-j+1)//2:
 9                     res+=1
10                 cnt[nums[j]]-=1
11         return res

C:3738. 替换至多一个元素后最长非递减子数组

可以修改一个元素,要求nums数组最长不下降子数组最长为多少。

如果对于i,有nums[i-1]<=nums[i+1],那么这个点最长的不下降子数组长度为1+左边+右边。

那么我们可以预处理好left和right数组,left[i]表示以nums[i]结尾的不下降子数组的最大长度,right同理。

此外,我们还需要考虑一下特殊情况,首先是不改,那么就是max(left),这和max(right)是一样的。

其次,改首元素和尾元素ans=max(ans,1+right[1],1+left[n-2])。

之后枚举改元素nums[i]的情况。

 1 class Solution:
 2     def longestSubarray(self, nums: List[int]) -> int:
 3         n=len(nums)
 4         left=[0]*n
 5         right=[0]*n
 6         left[0]=1
 7         for i in range(1,n):
 8             if nums[i]>=nums[i-1]:
 9                 left[i]=left[i-1]+1
10             else:
11                 left[i]=1
12         right[n-1]=1
13         for i in range(n-2,-1,-1):
14             if nums[i]<=nums[i+1]:
15                 right[i]=right[i+1]+1
16             else:
17                 right[i]=1
18         ans=max(left)
19         if n>1:
20             ans=max(ans,1+right[1],1+left[n-2])
21         for i in range(1,n-1):
22             l_part=left[i-1]+1
23             r_part=right[i+1]+1
24             ans=max(ans,l_part,r_part)
25             if nums[i+1]>=nums[i-1]:
26                 ans=max(ans,left[i-1]+right[i+1]+1)
27         return ans

D:3739. 统计主要元素子数组数目 II
接B,数据范围到1e5,不能用双重循环做。

假设将nums[i]==target置为1,nums[i]!=target置为-1,那么要求的就是对于pre[i],前面有多少个小于pre[i]的,注意pre[0]=1

可以用树状数组维护前面的每个pre的值有多少个,注意原数据的范围为[-n,n],总共2*n+1个数据,树状数组必须保证数据大于1,所以映射到[1,2n+1]范围。

 1 const int N = 2e5+10;
 2 int tr[N];
 3 int n;
 4 int lowbit(int x){
 5     return x&-x;
 6 }
 7 void add(int x,int c){
 8     for(int i=x;i<=2*n;i+=lowbit(i))
 9         tr[i]+=c;
10 }
11 int query(int x){
12     int ans=0;
13     for(int i=x;i;i-=lowbit(i)){
14         ans+=tr[i];
15     }
16     return ans;
17 }
18 class Solution {
19 public:
20     long long countMajoritySubarrays(vector<int>& nums, int target) {
21         n=nums.size();
22         for(int i=0;i<=n*2;i++)
23             tr[i]=0;
24         vector<int> pre(n+1,0);
25         for(int i=1;i<=n;i++){
26             pre[i]=pre[i-1]+(nums[i-1]==target?1:-1);
27         }
28         long long ans=0;
29         add(n+1,1);
30         for(int i=1;i<=n;i++){
31             if(pre[i]+n>0)
32                 ans+=query(pre[i]+n);
33             add(pre[i]+n+1,1);
34         }
35         return ans;
36     }
37 };

 

posted on 2025-11-14 13:15  greenofyu  阅读(0)  评论(0)    收藏  举报