首先让我们输出的是不操作的值。不定序,一看就很贪心。经过分类分类分类可证,\(a,b\) 都是升序(降序)的时候是最优的。
再看加操作的。相当于要维护这两个升序序列。我们发现,每次操作影响的值很少,最多两个值。在一个连续段中,修改的值相当于和末尾值交换,再加一。
唐点:
找这个末尾没必要维护一堆下标然后写挂,用个二分足以。反正用了排序,都是带 \(\log\) 的。
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define Linf 0x3f3f3f3f3f3f3f3f
#define pii pair<int, int>
#define int long long
#define all(v) v.begin(), v.end()
using namespace std;//#define filename "xxx"
#define FileOperations() freopen(filename".in", "r", stdin), freopen(filename".out", "w", stdout)namespace Traveller {const int N = 4e5+2, mod = 998244353;void mul(int &a, int b, int p = mod) { a = (a * b % p + p) % p; }int qpow(int a, int b, int p = mod) {int res = 1;a %= p;while(b) {if(b & 1) mul(res, a, p);b >>= 1;mul(a, a, p);}return res;} int inv(int a) { return qpow(a, mod-2); }int n, q;pii a[N], b[N];int c[N], d[N];int rev1[N], rev2[N];int ans;void work(pii *a, pii *b, int *c, int *rev, int x) {x = c[x];int y = upper_bound(a+1, a+n+1, pii(a[x].first, inf)) - a - 1;int p = rev[x], q = rev[y];//swapc[p] = y, c[q] = x;rev[x] = q, rev[y] = p;swap(x, y);mul(ans, inv(min(a[x].first, b[x].first)));mul(ans, min(++a[x].first, b[x].first));}void main() {cin >> n >> q;for(int i = 1, x; i <= n; ++i) {scanf("%lld", &x);a[i] = pii(x, i);}for(int i = 1, x; i <= n; ++i) {scanf("%lld", &x);b[i] = pii(x, i);}sort(a+1, a+n+1);sort(b+1, b+n+1);for(int i = 1; i <= n; ++i) c[a[i].second] = i, rev1[i] = a[i].second;for(int i = 1; i <= n; ++i) d[b[i].second] = i, rev2[i] = b[i].second;ans = 1;for(int i = 1; i <= n; ++i) mul(ans, min(a[i].first, b[i].first));printf("%lld ", ans);for(int i = 1, opt, x; i <= q; ++i) {scanf("%lld%lld", &opt, &x);if(opt == 1) work(a, b, c, rev1, x);else work(b, a, d, rev2, x);printf("%lld ", ans);}puts("");}
}signed main() {#ifdef filenameFileOperations();#endifint _;cin >> _;while(_--) Traveller::main();return 0;
}