Rank
A. 所有奇数长度子数组的和
暴力求解.
class Solution {
public:
int sumOddLengthSubarrays(vector<int>& arr) {
int n=arr.size(),ans=0;
for(int i=0;i<n;++i){
for(int j=i;j<n;++j){
if((j-i+1)&1){
for(int k=i;k<=j;++k) ans+=arr[k];
}
}
}
return ans;
}
};
B. 所有排列中的最大和
差分+贪心.
统计每个下标被计算的次数,对于每次查询,区间 [start,end]
中的所有下标被加入最终答案的次数都会+1,因此可以开辟一个差分数组 arr
,每次令 arr[start]+=1,arr[end+1]-=1
,所有查询结束后对 arr
求前缀和即可得到每个下标被累加的总次数,对 nums
和 arr
排序,让最大的 nums
与最大的 arr
相对应,最后求和.
class Solution {
public:
int arr[100050];
int maxSumRangeQuery(vector<int>& nums, vector<vector<int>>& requests) {
int n=nums.size();
int m=requests.size();
sort(nums.begin(),nums.end());
for(int i=0;i<m;++i){
int l=requests[i][0],r=requests[i][1];
arr[l]+=1;
arr[r+1]-=1;
}
for(int i=1;i<n;++i) arr[i]+=arr[i-1];
sort(arr,arr+n);
long long ans=0;
for(int i=n-1;i>=0;--i){
ans+=arr[i]*nums[i];
}
return ans%1000000007;
}
};
C. 使数组和能被 P 整除
数论+哈希.
假定下标 nums
从1到n,先求出 nums
的前缀和 sum
,如果 sum[n]%p=0
,则答案为0,否则假设 m=sum[n]%p
.
如果区间 [i,j],i<=j
满足要求,则 (sum[j]-sum[i-1])%p=m
,移项整理得 sum[i-1]=(sum[j]%p-m+p)%p
. 建立一个哈希表维护之前的 sum
与下标的对应关系,sum[x]
作为键,下标 x
作为值. 从左向右枚举 j
,找到距离 j
最近的 i<j
,且满足上式要求,即可记录答案,之后将 sum[j],j
加入哈希表,用于后续计算.
class Solution {
public:
typedef long long ll;
int minSubarray(vector<int>& nums, int p) {
int n=nums.size();
nums.insert(nums.begin(),0);
vector<ll> sum(n+1,0);
for(int i=1;i<=n;++i){
sum[i]=sum[i-1]+nums[i];
}
if(sum[n]%p==0) return 0;
int m=sum[n]%p;
int ans=n;
unordered_map<int,int> mp;
for(int j=0;j<=n;++j){
int x=(sum[j]%p-m+p)%p;
if(mp[x]>0 || x==0){
ans=min(ans,j-mp[x]);
}
mp[sum[j]%p]=j;
}
return ans<n?ans:-1;
}
};
D. 奇怪的打印机 II
模拟. 维护一个当前颜色集合 s
,颜色 0 表示颜色被删除,然后进行如下步骤.
遍历集合 s
,枚举 s
中的每一种颜色 col
:
- 如果图中所有的
col
加上若干颜色 0 能构成一个矩形区域,则将所有的col
变成 0,再将col
从s
中删除. 如果s
仍不为空,则继续枚举s
中的剩余颜色,然后重复相同的步骤. - 如果在
s
中找不到这样的col
,说明该状态是非法状态,返回false
.
最终 s
为空,返回 true
.
class Solution {
public:
bool isPrintable(vector<vector<int>>& g) {
set<int> s;
int n=g.size(),m=g[0].size();
for(int i=0;i<n;++i){
for(int j=0;j<m;++j){
s.insert(g[i][j]);
}
}
while(!s.empty()){
bool flag=false;
for(auto it=s.begin();it!=s.end();++it){
int col=(*it);
int sr=n,sc=m,er=-1,ec=-1;
for(int i=0;i<n;++i){
for(int j=0;j<m;++j){
if(g[i][j]==col){
sr=min(sr,i);
er=max(er,i);
sc=min(sc,j);
ec=max(ec,j);
}
}
}
bool ok=true;
for(int i=sr;i<=er;++i){
for(int j=sc;j<=ec;++j){
if(g[i][j]>0 && g[i][j]!=col){
ok=false;
}
}
}
if(!ok) continue;
for(int i=sr;i<=er;++i){
for(int j=sc;j<=ec;++j){
g[i][j]=0;
}
}
s.erase(it);
flag=true;
break;
}
if(!flag) return false;
}
return true;
}
};