2026.10.13 考试总结

考试总结

估:100 + 100 + 0 + 0

实:100 + 100 + 0 + 0 rk1

考的依托,t1 是假算,t4 考完 5mins 胡完,不知道为啥考试的时候不去做。该怎么处理我这呼热呼冷的手感。

T1

原:Field Should Not Be Empty

考虑算每个位置的贡献,首先对于 \(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\) 个,暴力算即可。做完了。

code

T2

原:Brukhovich and Exams

将代价分类,对于一段 \(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\) 价值即可。做完了。

code

T3

神秘随机化,不补。

T4

原:P9776 [HUSTFC 2023] 狭义线段树

我为什么不开,不然 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;
    }
}
posted @ 2026-10-13 21:44  ACehomoxue  阅读(7)  评论(0)    收藏  举报