首先让我们输出的是不操作的值。不定序,一看就很贪心。经过分类分类分类可证,\(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];
//swap
c[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 filename
FileOperations();
#endif
int _;
cin >> _;
while(_--) Traveller::main();
return 0;
}
标签:pii,int,题解,rev,CF2353D,mul,Refined,first,define
From: https://www.cnblogs.com/wfc284/p/18646313