A.
统计个数后,乘上
100
100
100除
n
n
n下取整即可
class Solution {
public:
int percentageLetter(string s, char letter) {
int n = s.size();
int c = 0;
for(auto u : s)
if(u == letter) c += 1;
int res = c * 100 / n;
return res;
}
};
B.
先计算每个背包的剩余可装数量,按剩余数量从小到大排序,依次尽量填充即可。
class Solution {
public:
int maximumBags(vector<int>& cap, vector<int>& rock, int rest) {
int n = cap.size();
for(int i = 0; i < n; ++i)
cap[i] -= rock[i];
sort(cap.begin(), cap.end());
int res = 0;
for(int i = 0; i < n; ++i) {
int mn = min(rest, cap[i]);
if(mn == cap[i]) res += 1;
rest -= mn;
}
return res;
}
};
C.
比较每个相邻线段的斜率是否相同即可
class Solution {
public:
int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
int minimumLines(vector<vector<int>>& s) {
sort(s.begin(), s.end(), [](const vector<int>& A, const vector<int>& B) {
return A[0] < B[0];
});
int res = 0;
int n = s.size();
int prex = 0, prey = 0, pref = 1;
for(int i = 1; i < n; ++i) {
int ych = s[i][1] - s[i - 1][1];
int xch = s[i][0] - s[i - 1][0];
int fch = 1;
if(ych < 0) fch = -1, ych = -ych;
int g = gcd(xch, ych);
xch /= g, ych /= g;
if(prex == 0) {
res += 1;
} else {
if(pref != fch || prex != xch || prey != ych) {
res += 1;
}
}
prex = xch;
prey = ych;
pref = fch;
}
return res;
}
};
D.
枚举每个值
a
i
a_i
ai?作为最小值的区间,我们称
a
i
a_i
ai?作为最小值的区间为区间
i
i
i。 为了防止重复计算,
a
i
a_i
ai?的最远左端点为
i
i
i左边第一个
j
j
j,存在
a
j
<
a
i
a_j<a_i
aj?<ai?
a
i
a_i
ai?的最远右端点为
i
i
i右边第一个
k
k
k,存在
a
k
≤
a
i
a_k\leq a_i
ak?≤ai?
区间
i
i
i的左边有
i
?
j
i-j
i?j种选择,即选择
a
i
?
1
a_{i-1}
ai?1?、选择
a
i
?
1
,
a
i
?
2
a_{i-1},a_{i-2}
ai?1?,ai?2?、…、选择
a
i
?
1
,
.
.
.
,
a
j
?
1
a_{i-1},...,a_{j-1}
ai?1?,...,aj?1? 区间
j
j
j的右边有
k
?
i
k-i
k?i种选择,即选择
a
i
+
1
a_{i+1}
ai+1?、选择
a
i
+
1
,
a
i
+
2
a_{i+1},a_{i+2}
ai+1?,ai+2?、…、选择
a
i
+
1
,
.
.
.
,
a
k
?
1
a_{i+1},...,a_{k-1}
ai+1?,...,ak?1?
那么计算所有区间
i
i
i的和,就可以转换为求区间
i
i
i的左边选择, 以及区间
i
i
i的右边选择。 我们可以维护前缀和
p
r
e
pre
pre,后缀和
s
u
f
suf
suf,双重前缀和
p
p
r
e
ppre
ppre,以及双重后缀和
s
s
u
f
ssuf
ssuf。
双重前缀和
ppre[1] = 1 * a[1]
ppre[2] = 1 * a[1] + 2 * a[2]
ppre[3] = 1 * a[1] + 2 * a[2] + 3 * a[3]
...
ppre[n] = 1 * a[1] + 2 * a[2] + ... + n * a[n]
双重后缀和
ssuf[n] = 1 * a[n]
ssuf[n - 1] = 1 * a[n] + 2 * a[n - 1]
ssuf[n - 2] = 1 * a[n] + 2 * a[n - 1] + 3 * a[n - 2]
...
ssuf[n] = 1 * a[n] + 2 * a[n - 1] + ... + n * a[1]
计算
a
j
+
1
a_{j+1}
aj+1?到
a
k
?
1
a_{k-1}
ak?1?这个区间的和,可以分为三部分:
-
a
j
+
1
a_{j+1}
aj+1?到
a
i
?
1
a_{i-1}
ai?1?的双重前缀和
L
v
=
p
p
r
e
i
?
1
?
p
p
r
e
j
?
j
×
(
p
r
e
i
?
1
?
p
r
e
j
)
Lv = ppre_{i-1}-ppre_{j}-j\times (pre_{i-1}-pre_{j})
Lv=pprei?1??pprej??j×(prei?1??prej?)
-
a
k
?
1
a_{k-1}
ak?1?到
a
i
+
1
a_{i+1}
ai+1?的双重后缀和
R
v
=
s
s
u
f
i
+
1
?
s
s
u
f
k
?
(
n
?
k
+
1
)
×
(
s
u
f
i
+
1
?
s
u
f
k
)
Rv = ssuf_{i+1}-ssuf_{k}-(n-k+1)\times (suf_{i+1}-suf_{k})
Rv=ssufi+1??ssufk??(n?k+1)×(sufi+1??sufk?)
-
a
i
a_i
ai?作为区间最小值的总和
M
v
=
a
i
×
(
k
?
j
?
1
)
Mv = a_i\times (k-j-1)
Mv=ai?×(k?j?1)
其中
L
v
Lv
Lv出现了
k
?
i
k-i
k?i次,
R
v
Rv
Rv出现了
i
?
j
i-j
i?j次。
L
v
Lv
Lv对区间的总和贡献为
L
v
×
(
k
?
i
)
Lv\times (k-i)
Lv×(k?i)
R
v
Rv
Rv对区间的总和贡献为
R
v
×
(
i
?
j
)
Rv\times (i-j)
Rv×(i?j)
M
v
Mv
Mv对区间的总和贡献为
M
v
Mv
Mv
答案即为
∑
i
=
1
n
a
i
×
(
L
v
+
R
v
+
M
v
)
\sum_{i=1}^n a_i\times (Lv+Rv+Mv)
i=1∑n?ai?×(Lv+Rv+Mv)
typedef long long ll;
class Solution {
public:
const int mod = 1e9 + 7;
int totalStrength(vector<int>& a) {
ll res = 0;
int n = a.size();
vector<int> Lrank(n + 2, 0), Rrank(n + 2, 0);
for(int i = 1; i <= n; ++i) Lrank[i] = i, Rrank[n - i + 1] = i;
vector<ll> ppre(n + 2, 0), ssuf(n + 2, 0);
vector<ll> pre(n + 2, 0), suf(n + 2, 0);
for(int i = 1; i <= n; ++i) pre[i] = (pre[i - 1] + a[i - 1]) % mod;
for(int i = n; i >= 1; --i) suf[i] = (suf[i + 1] + a[i - 1]) % mod;
for(int i = 1; i <= n; ++i) ppre[i] = (ppre[i - 1] + 1ll * a[i - 1] * Lrank[i] % mod) % mod;
for(int i = n; i >= 1; --i) ssuf[i] = (ssuf[i + 1] + 1ll * a[i - 1] * Rrank[i] % mod) % mod;
vector<int> Rfirst(n + 2, 0);
vector<int> Lfirst(n + 2, 0);
stack<int> stk;
for(int i = 1; i <= n; ++i) {
while(!stk.empty() && a[stk.top() - 1] >= a[i - 1]) stk.pop();
if(!stk.empty()) Lfirst[i] = stk.top();
else Lfirst[i] = 0;
stk.push(i);
}
while(!stk.empty()) stk.pop();
for(int i = n; i >= 1; --i) {
while(!stk.empty() && a[stk.top() - 1] > a[i - 1]) stk.pop();
if(!stk.empty()) Rfirst[i] = stk.top();
else Rfirst[i] = n + 1;
stk.push(i);
}
for(int i = 1; i <= n; ++i) {
ll Lf = Lfirst[i];
ll Lv = ((ppre[i - 1] - ppre[Lf]) % mod + mod) % mod;
Lv = (Lv - 1ll * Lrank[Lf] * (pre[i - 1] - pre[Lf]) % mod + mod) % mod;
ll Rf = Rfirst[i];
ll Rv = ((ssuf[i + 1] - ssuf[Rf]) % mod + mod) % mod;
Rv = (Rv - 1ll * Rrank[Rf] * (suf[i + 1] - suf[Rf]) % mod + mod) % mod;
ll Mv = 1ll * (i - Lf) * (Rf - i) % mod * a[i - 1] % mod;
ll temp = (Lv * (Rf - i) % mod + Rv * (i - Lf) % mod) % mod;
ll sum = (temp + Mv) % mod;
res = (res + 1ll * sum * a[i - 1] % mod) % mod;
}
return res;
}
};
|