A:3736. 最小操作次数使数组元素相等 III
签到题。
1 class Solution: 2 def minMoves(self, nums: List[int]) -> int: 3 return max(nums)*len(nums)-sum(nums)
数据范围小,枚举左端点和右端点就能过,注意这里有一个技巧,我之前这种都是写三重循环的。
但是其实可以枚举左端点之后,从左端点扫到尾,然后右端点从右往左枚举,同时维护一下外层循环的数据。
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
可以修改一个元素,要求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 };
浙公网安备 33010602011771号