2026.10.13 考试总结
考试总结
估:100 + 100 + 0 + 0
实:100 + 100 + 0 + 0 rk1
考的依托,t1 是假算,t4 考完 5mins 胡完,不知道为啥考试的时候不去做。该怎么处理我这呼热呼冷的手感。
T1
考虑算每个位置的贡献,首先对于 \(i\) 不为 \(p_i\),把 \(i\) 换到 \(p_i\) 显然有贡献,这里有用的交换有 \(n\) 个。对于 \(p_i = i\),考虑前面有几个 \(j\) 有 \(p_j > i\),如果没有,那么当交换的 \([l, r]\) 不包含 \(j\) 那么 \(j\) 就有贡献,设 \(s0_i\) 表示前 \(i\) 位置有多少个这样的点。对于前面有 \(1\) 个这样的 \(j\),那么把 \(j\) 换到后面一定唯一存在的 \(k > i \land p_k < i\) 的位置(即交换 \((j, k)\)),\(i\) 就会有 \(1\) 的贡献。不难发现有用的交换只有不超过 \(n\) 个,暴力算即可。做完了。
T2
将代价分类,对于一段 \(a\) 上为 1 1 1 1 1 1,长度为 \(len\),如果不在 \(a\) 的头尾,那么都要改 \(len\) 次并消掉 \(len + 1\) 个 \(\gcd(a_i, a_{i + 1}) = 1\) 的位置,理解为 \(len\) 代价 \(len + 1\) 价值;如果位于序列头尾,那么就是 \(len\) 代价 \(len\) 价值,拆成 \(len\) 个 \(1\) 代价 \(2\) 价值。对于一段 \(a_{[l, r]}\) 有 \(\forall k \in [l, r] \land \gcd(a_k, a_{k + 1}) = 1\),假设长度为 \(len\),不难发现我们有 \(\lfloor \frac {len} 2 \rfloor\) 个 \(1\) 代价 \(2\) 价值,\(len \bmod 2\) 个 \(1\) 代价 \(2\) 价值。最后统计答案,考虑算最开始 \(\gcd(a_i, a_{i + 1}) = 1\) 的个数然后减去最大价值。对于计算最大价值,显然贪心,先取 \(1\) 代价 \(2\) 价值的,然后取 \(len\) 代价 \(len + 1\) 价值,\(len\) 显然应从小到大取,取不完的显然可以转换成 \(len\) 个 \(1\) 代价 \(1\) 价值,最后再去剩下的 \(1\) 代价 \(1\) 价值即可。做完了。
T3
神秘随机化,不补。
T4
我为什么不开,不然 300pts 了。
我的做法没什么思维难度,但代码有点长。
考虑拆开操作一和操作二对查询的贡献。对于操作二,不难发现我们可以求出 \([s, t]\) 对应的叶子区间,线段树或 st 表都是简单的,然后直接线段树区间加即可,不难发现其对区间查询 \([l, r]\) 的贡献就是线段树这一区间的和。
现在考虑操作一。考虑对于点 \(i\),假设 \(v_i\) 表示 \(i\) 被操作一加的和,那么对于区间查询 \([l, r]\),\(i\) 的贡献显然为 \([l, r]\) 中属于 \(i\) 的儿子的个数乘 \(i\)。对于区间 \([l, r]\) 完整包含的一个线段树节点 \([fl, fr]\),不难发现其贡献为 \((fr - fl + 1) v_i\),这对于每一个节点都是固定的,每个点存上他和他所有子树节点的答案,这一部分可以区间加权加线段树查,单次修改时间复杂度 \(O(\log n)\)。由于只有 \(\log n\) 个这样的区间,单次查时间复杂度 \(O(\log ^ 2 n)\)。对于与 \([l, r]\) 相交的区间 \([fl, fr]\),贡献显然为 \((\min(fr, r) - \max(fl, l) + 1) v_i\),这样的区间也只有 \(\log n\) 个,每次查 \(v_i\) 再乘上即可,单次查时间复杂度 \(O(\log ^ 2n)\)。这样就可以做到一共 \(O(n \log ^ 2 n)\) 算完操作一的贡献。
每次操作三查询,把操作一和操作二的贡献加起来即可。做完了。
code
#include <bits/stdc++.h>
using namespace std;
#define int ll
#define ll long long
#define usd unsigned
#define el putchar('\n')
#define lowbit(x) (x & (-x))
#define AC return
#define AK return 0
#define YS cout << "YES"
#define NO cout << "NO"
#define Ys cout << "Yes"
#define No cout << "No"
#define ys cout << "yes"
#define no cout << "no"
#define ls(i) ch[i][0]
#define rs(i) ch[i][1]
#define debug(num) cerr << #num << ' ' << num << '\n'
#define void inline void
#define il inline
#define Mod(x) (((x) % mod + mod) % mod)
#define pii pair <int, int>
#define pll pair <ll, ll>
il char gc() { char c; while((c = getchar()) <= ' ') ; return c; }
il int rd() {
char c; int x, f = 1;
while(!isdigit(c = getchar())) if(c == '-') f *= -1;
x = c ^ 48;
while(isdigit(c = getchar())) x = (x << 3) + (x << 1) + (c ^ 48);
return x * f;
}
void ACehomoxue();
signed main() {
srand(time(0));
// freopen(".in", "r", stdin);
// freopen(".out", "w", stdout);
int t = 1;
// t = rd();
while(t--) ACehomoxue();
AK;
}
const int mod = 998244353, maxn = 2 * 1e5 + 18;
class xds2 {
struct tree { int l, r, v, t; } t[maxn << 2];
void push_up(int i) { t[i].v = t[i << 1].v + t[i << 1 | 1].v; }
void mdf(int i, int x) { t[i].v = (t[i].v + (t[i].r - t[i].l + 1) * x) % mod, t[i].t = (t[i].t + x) % mod; }
void push_down(int i) { mdf(i << 1, t[i].t), mdf(i << 1 | 1, t[i].t), t[i].t = 0; }
public:
void build(int i, int l, int r) {
t[i].l = l, t[i].r = r;
if(l == r) AC;
int mid = l + r >> 1;
build(i << 1, l, mid);
build(i << 1 | 1, mid + 1, r);
}
void updata(int i, int l, int r, int x) {
if(t[i].r < l || t[i].l > r) AC;
if(t[i].l >= l && t[i].r <= r) { mdf(i, x); AC; } else push_down(i);
updata(i << 1, l, r, x), updata(i << 1 | 1, l, r, x), push_up(i);
}
il int query(int i, int l, int r) {
if(l > t[i].r || t[i].l > r) AK;
if(t[i].l >= l && t[i].r <= r) return t[i].v;
push_down(i);
return (query(i << 1, l, r) + query(i << 1 | 1, l, r)) % mod;
}
} sum;
class valxds {
struct tree { int l, r, v, t, s, mn, mx; } t[maxn << 2];
void push_up(int i) {
t[i].s = (t[i << 1].s + t[i << 1 | 1].s) % mod;
t[i].mn = min(t[i << 1].mn, t[i << 1 | 1].mn);
t[i].mx = max(t[i << 1].mx, t[i << 1 | 1].mx);
t[i].v = (t[i << 1].v + t[i << 1 | 1].v) % mod;
}
void mdf(int i, int x) { t[i].v = (t[i].v + t[i].s * x) % mod, t[i].t = (t[i].t + x) % mod; }
void push_down(int i) { mdf(i << 1, t[i].t), mdf(i << 1 | 1, t[i].t), t[i].t = 0; }
public:
void build(int i, int l, int r) {
t[i].l = l, t[i].r = r, t[i].mn = 1e9, t[i].mx = 0;
if(l == r) AC;
int mid = l + r >> 1;
build(i << 1, l, mid);
build(i << 1 | 1, mid + 1, r);
}
void updmms(int i, int p, int mn, int mx, int s) {
if(t[i].l == t[i].r) { t[i].mn = mn, t[i].mx = mx, t[i].s = s; AC; }
push_down(i);
int mid = t[i].l + t[i].r >> 1;
if(p <= mid) updmms(i << 1, p, mn, mx, s);
else updmms(i << 1 | 1, p, mn, mx ,s);
push_up(i);
}
il int get(int i, int p) {
if(t[i].l == t[i].r) return t[i].t;
push_down(i);
int mid = t[i].l + t[i].r >> 1;
if(p <= mid) return get(i << 1, p);
else return get(i << 1 | 1, p);
}
void updata(int i, int l, int r, int x) {
if(t[i].l >= l && t[i].r <= r) {
mdf(i, x);
AC;
}
push_down(i);
int mid = t[i].l + t[i].r >> 1;
if(l <= mid) updata(i << 1, l, r, x);
if(r > mid) updata(i << 1 | 1, l, r, x);
push_up(i);
}
il int query(int i, int l, int r) {
if(t[i].l >= l && t[i].r <= r) return t[i].v;
push_down(i);
int mid = t[i].l + t[i].r >> 1, res = 0;
if(l <= mid) res = (res + query(i << 1, l, r)) % mod;
if(r > mid) res = (res + query(i << 1 | 1, l, r)) % mod;
return res;
}
il int getmin(int i, int l, int r) {
if(t[i].l >= l && t[i].r <= r) return t[i].mn;
push_down(i);
int mid = t[i].l + t[i].r >> 1, res = 1e9;
if(l <= mid) res = min(res, getmin(i << 1, l, r));
if(r > mid) res = min(res, getmin(i << 1 | 1, l, r));
return res;
}
il int getmax(int i, int l, int r) {
if(t[i].l >= l && t[i].r <= r) return t[i].mx;
push_down(i);
int mid = t[i].l + t[i].r >> 1, res = 0;
if(l <= mid) res = max(res, getmax(i << 1, l, r));
if(r > mid) res = max(res, getmax(i << 1 | 1, l, r));
return res;
}
} ds;
int n, dfn = 0, ch[maxn][2], out[maxn];
void build(int &i, int fl = 1, int fr = n) {
i = ++dfn;
ds.updmms(1, i, fl, fr, fr - fl + 1);
if(fl == fr) { out[i] = i; AC; }
int mid = fl + fr >> 1;
build(ls(i), fl, mid);
build(rs(i), mid + 1, fr);
out[i] = dfn;
}
il int query(int i, int l, int r, int fl = 1, int fr = n) {
if(fl >= l && fr <= r) return ds.query(1, i, out[i]);
int mid = fl + fr >> 1, res = (min(fr, r) - max(fl, l) + 1) * ds.get(1, i) % mod;
if(l <= mid) res = (res + query(ls(i), l, r, fl, mid)) % mod;
if(r > mid) res = (res + query(rs(i), l, r, mid + 1, fr)) % mod;
return res;
}
void ACehomoxue() {
n = rd();
ds.build(1, 1, 2 * n - 1), sum.build(1, 1, n);
int usl; build(usl);
for(int i = 2 * n - 2; i--; ) rd();
for(int q = rd(), opt, l, r; q--; ) {
opt = rd(), l = rd(), r = rd();
if(opt == 1) ds.updata(1, l, r, rd());
if(opt == 2) sum.updata(1, ds.getmin(1, l, r), ds.getmax(1, l, r), rd());
if(opt == 3) cout << (query(1, l, r) + sum.query(1, l, r)) % mod, el;
}
}

浙公网安备 33010602011771号