Codeforces Round 1028 (Div. 2) B. Gellyfish and Baby’s Breath
题目
Flower gives Gellyfish two permutations ∗ ^{\text{∗}} ∗ of [ 0 , 1 , … , n − 1 ] [0, 1, \ldots, n-1] [0,1,…,n−1]: p 0 , p 1 , … , p n − 1 p_0, p_1, \ldots, p_{n-1} p0,p1,…,pn−1 and q 0 , q 1 , … , q n − 1 q_0, q_1, \ldots, q_{n-1} q0,q1,…,qn−1.
Now Gellyfish wants to calculate an array r 0 , r 1 , … , r n − 1 r_0,r_1,\ldots,r_{n-1} r0,r1,…,rn−1 through the following method:
- For all i i i ( 0 ≤ i ≤ n − 1 0 \leq i \leq n-1 0≤i≤n−1), r i = max j = 0 i ( 2 p j + 2 q i − j ) r_i = \max\limits_{j=0}^{i} \left(2^{p_j} + 2^{q_{i-j}} \right) ri=j=0maxi(2pj+2qi−j)
But since Gellyfish is very lazy, you have to help her figure out the elements of r r r.
Since the elements of r r r are very large, you are only required to output the elements of r r r modulo 998 244 353 998\,244\,353 998244353.
∗ ^{\text{∗}} ∗An array b b b is a permutation of an array a a a if b b b consists of the elements of a a a in arbitrary order. For example, [ 4 , 2 , 3 , 4 ] [4,2,3,4] [4,2,3,4] is a permutation of [ 3 , 2 , 4 , 4 ] [3,2,4,4] [3,2,4,4] while [ 1 , 2 , 2 ] [1,2,2] [1,2,2] is not a permutation of [ 1 , 2 , 3 ] [1,2,3] [1,2,3].
Input
Each test contains multiple test cases. The first line contains the number of test cases t t t ( 1 ≤ t ≤ 10 4 1 \le t \le 10^4 1≤t≤104). The description of the test cases follows.
The first line of each test case contains a single integer n n n ( 1 ≤ n ≤ 10 5 1 \leq n \leq 10^5 1≤n≤105).
The second line of each test case contains n n n integers p 0 , p 1 , … , p n − 1 p_0, p_1, \ldots,p_{n-1} p0,p1,…,pn−1 (KaTeX parse error: Expected 'EOF', got '&' at position 12: 0 \leq p_i &̲lt; n).
The third line of each test case contains n n n integers q 0 , q 1 , … , q n − 1 q_0, q_1, \ldots,q_{n-1} q0,q1,…,qn−1 (KaTeX parse error: Expected 'EOF', got '&' at position 12: 0 \leq q_i &̲lt; n).
It is guaranteed that both p p p and q q q are permutations of [ 0 , 1 , … , n − 1 ] [0, 1, \ldots, n-1] [0,1,…,n−1].
It is guaranteed that the sum of n n n over all test cases does not exceed 10 5 10^5 105.
Output
For each test case, output n n n integers r 0 , r 1 , … , r n − 1 r_0, r_1, \ldots, r_{n-1} r0,r1,…,rn−1 in a single line, modulo 998 244 353 998\,244\,353 998244353.
题目解析及思路
题目要求对于两个[0,...,n]
的排列p,q ,求出r的所有元素
样例输入
3
0 2 1
1 2 0
样例输出
3 6 8
- r 0 = 2 p 0 + 2 q 0 = 1 + 2 = 3 r_0 = 2^{p_0} + 2^{q_0} = 1+2=3 r0=2p0+2q0=1+2=3
- r 1 = max ( 2 p 0 + 2 q 1 , 2 p 1 + 2 q 0 ) = max ( 1 + 4 , 4 + 2 ) = 6 r_1 = \max(2^{p_0} + 2^{q_1}, 2^{p_1} + 2^{q_0}) = \max(1+4, 4+2) = 6 r1=max(2p0+2q1,2p1+2q0)=max(1+4,4+2)=6
- r 2 = max ( 2 p 0 + 2 q 2 , 2 p 1 + 2 q 1 , 2 p 2 + 2 q 0 ) = ( 1 + 1 , 4 + 4 , 2 + 2 ) = 8 r_2 = \max(2^{p_0} + 2^{q_2}, 2^{p_1}+2^{q_1}, 2^{p_2}+2^{q_0}) = (1+1, 4+4, 2+2) = 8 r2=max(2p0+2q2,2p1+2q1,2p2+2q0)=(1+1,4+4,2+2)=8
代码
/*
首先是贪心的考虑:r的最终取值一定会取最大的p或最大的q构成的组合
维护两个对组pp和qq,从前往后枚举不同区间时 first存此前最大的p(q),second存对应的q(p),方便在后续找最大时调用
*/
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define MOD 998244353
//快速幂求2的n次方
ll mod_pow(ll base, ll exp, ll mod) {
ll result = 1;
base %= mod;
while (exp > 0) {
if (exp & 1) result = result * base % MOD;
base = base * base % MOD;
exp >>= 1;
}
return result;
}
void solve() {
int n;
cin >> n;
vector<int> p(n), q(n);
for (auto &i : p) cin >> i;
for (auto &i : q) cin >> i;
vector<pair<int, int>> pp(n), qq(n);
//维护最大p和最大p的下标
int max_p = -1, ind_p = -1;
for (int i = 0; i < n; i++) {
if (max_p < p[i] ) {
max_p = p[i];
ind_p = i;
}
pp[i].first = max_p;
//i-ind为对应的q的下标,second存对应q
pp[i].second = (i - ind_p >= 0) ? q[i - ind_p] : 0;
}
//同理求qq
int max_q = -1, ind_q = -1;
for (int i = 0; i < n; i++) {
if (max_q < q[i] ) {
max_q = q[i];
ind_q = i;
}
qq[i].first = max_q;
//存对应p
qq[i].second = (i - ind_q >= 0) ? p[i - ind_q] : 0;
}
vector<ll> r(n);
for (int i = 0; i < n; i++) {
//a1,a2为最大p和对应q
ll a1 = mod_pow(2, pp[i].first, MOD);
ll a2 = mod_pow(2, pp[i].second, MOD);
//b1,b2为最大q和对应p
ll b1 = mod_pow(2, qq[i].first, MOD);
ll b2 = mod_pow(2, qq[i].second, MOD);
//如果第一个组合中最大值比第二个组合中最大值还*大*
//肯定取第一个组合
if (max(pp[i].first,pp[i].second) > max(qq[i].first,qq[i].second)) {
r[i] = (a1 + a2) % MOD;
}
//如果第一个组合中最大值比第二个组合中最大值还*小*
//肯定取第二个组合
else if(max(pp[i].first,pp[i].second) < max(qq[i].first,qq[i].second)){
r[i] = (b1 + b2) % MOD;
}
//如果最大值相同,比另一个值/比二者之和 两种方法都可以
else if(pp[i].first+pp[i].second > qq[i].first+qq[i].second){
r[i] = (a1 + a2) % MOD;
}
else {
r[i] = (b1 + b2) % MOD;
}
}
for (int i = 0; i < n; i++) {
cout << r[i] << " ";
}
cout << "\n";
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
ll t;
cin >> t;
while (t--) {
solve();
}
return 0;
}