概述
B. 小w的a=b问题
思路:把阶乘hash就行
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1e5 + 10, N = 1e5;
const int mod1 = 1e9 + 7, mod2 = 998244353;
ll p1[maxn], p2[maxn];
int main() {
p1[0] = p2[0] = 1;
for (int i = 1; i <= N; i++) {
p1[i] = p1[i - 1] * i % mod1;
p2[i] = p2[i - 1] * i % mod2;
}
int T;
cin>>T;
while (T--) {
int n, m, x;
ll s1 = 1, s2 = 1;
cin>>n>>m;
for (int i = 1; i <= n; i++) {
cin>>x;
s1 *= p1[x]; s1 %= mod1;
s2 *= p2[x]; s2 %= mod2;
}
ll s3 = 1, s4 = 1;
for (int i = 1; i <= m; i++) {
cin>>x;
s3 *= p1[x]; s3 %= mod1;
s4 *= p2[x]; s4 %= mod2;
}
if (s1 == s3 && s2 == s4)
puts("equal");
else
puts("unequal");
}
}
C. 小w的糖果
我们维护一下差分数组sum,操作:1 x 就是sum[x]++,操作:2 x 就是sum[x] 到 sum[n] +=1,操作3不好搞了,我们记S数组也是差分数组,不过假设S[i] = x,那么S[i] 真正的值是(2 * i - 1) * x,那么操作:3 x 可以这样转化:S[x] 到 S[n] +=1,sum[x] 到 sum[n] -= 2 * (x - 1),这一步你们自己推一推,我们发现,对于差分数组区间加减法,可以再进行一次差分,差分套差分O(n)搞定这题
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1e5 + 10, mod = 1e9 + 7;
ll sum[2][maxn], a[maxn];
void add(ll &x, ll y) {
x += y;
if (x >= mod)
x -= mod;
if (x < 0)
x += mod;
}
int main() {
int T;
cin>>T;
while (T--) {
int n, q, opt, x;
cin>>n>>q;
for (int i = 1; i <= n; i++)
for (int j = 0; j < 2; j++)
sum[j][i] = 0;
while (q--) {
cin>>opt>>x;
if (opt == 1)
add(sum[0][x], 1), add(sum[0][x + 1], -1);
else if (opt == 2)
add(sum[0][x], 1);
else {
add(sum[1][x], 1);
add(sum[0][x], -(x - 1) * 2);
}
}
for (int i = 1; i <= n; i++) {
add(sum[0][i], sum[0][i - 1]);
add(sum[1][i], sum[1][i - 1]);
a[i] = sum[0][i] + sum[1][i] * (2 * i - 1) % mod;
a[i] %= mod;
add(a[i], 0);
}
for (int i = 1; i <= n; i++) {
add(a[i], a[i - 1]);
printf("%lld", a[i]);
if (i != n)
printf(" ");
else
puts("");
}
}
}
E. 小w的矩阵前k大元素
思路:对于每一次查询,我们先用两个set:s1,s2 维护当前a数组前x个元素和b数组前y个元素,并且用一颗权值线段树维护b数组前y个元素,如果要查询前k小的元素,我们二分求第k小的元素mid,判断方法:枚举第一个set的元素x,从权值线段树中找 <= mid - x的元素有多少个,然后和k对比就行。假设找到了mid = ans,那么我们再枚举两个set的元素 t1, t2,把所有满足: t1 + t2 < mid 的元素加入优先队列,然后输出就行,复杂度:klognlogn
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1e5 + 10, M = 1e9;
ll a[maxn], b[maxn], N = 4e9;;
multiset<ll> s1, s2;
priority_queue<ll, vector<ll>, greater<ll> > Q;
int sum[maxn * 40], ls[maxn * 40], rs[maxn * 40];
int cnt, rt;
void up(int& o, ll l, ll r, ll k) {
if (!o)
o = ++cnt;
sum[o]++;
if (l == r)
return;
ll m = (l + r) / 2;
if (k <= m)
up(ls[o], l, m, k);
else
up(rs[o], m + 1, r, k);
}
int qu(int o, ll l, ll r, ll k) {
if (r <= k)
return sum[o];
ll m = (l + r) / 2;
int res = qu(ls[o], l, m, k);
if (k > m)
res += qu(rs[o], m + 1, r, k);
return res;
}
int ok(ll T, int k) {
int res = 0;
for (auto x : s1) {
if (T - x < 0)
return 0;
int tmp = qu(rt, 0, N, T - x);
if (!tmp)
return 0;
res += tmp;
if (res >= k)
return 1;
}
return 0;
}
int main() {
int n, m, q;
scanf("%d%d%d", &n, &m, &q);
for (int i = 1; i <= n; i++)
scanf("%lld", &a[i]), a[i] += M;
for (int i = 1; i <= m; i++)
scanf("%lld", &b[i]), b[i] += M;
int x = 1, y = 1, d;
s1.insert(a[1]);
s2.insert(b[1]);
up(rt, 0, N , b[1]);
char s[2];
while (q--) {
scanf("%s%d", s, &d);
if (s[0] == 'R') {
for (int i = y + 1; i <= min(m, y + d); i++)
s2.insert(b[i]), up(rt, 0, N, b[i]);
y += d;
y = min(y, m);
}
else if(s[0] == 'D') {
for (int i = x + 1; i <= min(n, x + d); i++)
s1.insert(a[i]);
x += d;
x = min(x, n);
}
else {
ll l = 0, r = N;
while (l < r) {
ll m = (l + r) / 2;
if (ok(m, d))
r = m;
else
l = m + 1;
}
int res = 0;
for (auto t1 : s1) {
int flag = 0;
for (auto t2 : s2) {
if (t1 + t2 < l)
Q.push(t1 - M + t2 - M), flag = 1;
else
break;
}
if (!flag)
break;
}
while (!Q.empty() && d) {
printf("%lld", Q.top());
Q.pop();
d--;
if (d)
printf(" ");
}
while (d--) {
printf("%lld", l - M * 2);
if (d)
printf(" ");
}
puts("");
}
}
}
最后
以上就是淡淡大炮为你收集整理的牛客练习赛48 部分题解的全部内容,希望文章能够帮你解决牛客练习赛48 部分题解所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复