LAOI-2 VP 记

VP?锐评!

省流:350 pts。unr 是真没人打。

A

赛时:真让你整上去了啊,还 $\max$ 整除 $\min$,还保证题面没有任何问题?

直接类似分块地维护颜色段,整段预处理段间前缀答案,散段直接算。

#include <cstdio>
#include <algorithm>
#define F(x, y) ((y - x + 1ll) * (y - x + 2) >> 1)
using namespace std;
int n, m, c, a[200050], t[200050], l[200050], r[200050];
long long s[200050];
int main()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i)
        scanf("%d", a + i), a[i] == a[r[c]] ? ++r[c] : l[c] = r[++c] = i, t[i] = c;
    for (int i = 1; i <= c; ++i)
        s[i] = s[i - 1] + F(l[i], r[i]);
    scanf("%d", &m);
    for (int i = 0, o, x, y; i < m; ++i)
    {
        scanf("%d%d", &o, &x);
        if (o & 1)
            (a[++n] = x) == a[r[c]] ? ++r[c] : l[c] = r[++c] = n, s[t[n] = c] = s[c - 1] + F(l[c], r[c]);
        else
            scanf("%d", &y), printf("%lld\n", (t[x] == t[y] ? F(x, y) : F(x, r[t[x]]) + s[t[y] - 1] - s[t[x]] + F(l[t[y]], y)) % 1000000007);
    }
    return 0;
}

忘取模 WA 了好几发,哈哈。


赛后:std 带 $\log$ 啊,那我是不是爆标了。

橙($O(n\log n)$) / 黄($O(n)$),作为 A 出的不错,除了匪夷所思的题面。

B

赛时:下次别让 ZYH 验题了,免得模板线段树又被搬上来。

$k$ 个 $x$ 拼起来就是 $x\sum\limits_{i=0}^{k-1}10^{i\lfloor\log_{10}x+1\rfloor}$,预处理后面的东西。

感觉没意思,不如写个 ODT 看看数据造的怎么样。

#include <set>
#include <cmath>
#include <cstdio>
#define M 998244353
using namespace std;
struct N
{
    int l, r, v;
    bool operator<(N b) const { return l < b.l; }
};
set<N> s;
set<N>::iterator i, j;
set<N>::iterator S(int k)
{
    i = s.lower_bound({k});
    if (i != s.end() && i->l == k)
        return i;
    int l = (--i)->l, r = i->r, v = i->v;
    s.erase(i);
    s.insert({l, k - 1, v});
    return s.insert({k, r, v}).first;
}
long long x = 1, y, p[2000050];
int n, m, f[200050][10];
int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 1, v; i <= n; ++i, x = x * 10 % M)
    {
        scanf("%d", &v);
        s.insert({i, i, v});
        for (int j = y = 1; j <= 9; ++j)
            f[i][j] = (f[i - 1][j] + (y = y * x % M)) % M;
    }
    for (int i = p[0] = 1; i <= n * 9; ++i)
        p[i] = p[i - 1] * 10 % M;
    for (int T = 0, o, l, r, k; T < m; ++T)
    {
        scanf("%d%d%d", &o, &l, &r);
        j = S(r + 1);
        i = S(l);
        if (o & 1)
            scanf("%d", &k), s.erase(i, j), s.insert({l, r, k});
        else
        {
            x = 0;
            for (int v; i != j; ++i)
                v = log10(i->v) + 1, x = (x * p[v * (i->r - i->l + 1)] + 1ll * i->v * f[i->r - i->l + 1][v]) % M;
            printf("%lld\n", x);
        }
    }
    return 0;
}

sb 错误 WA 了好几发,哈哈。

真的被卡了啊,看来数据还是有一定水平。

#include <cmath>
#include <cstdio>
#define M 998244353
#define G int m = b[p].s + b[p].t >> 1
using namespace std;
int n, m, c, r, p[2000050], f[200050][10];
long long x;
struct T
{
    int l, r, s, t, x, z;
    long long v;
    T(int s = 0, int t = 0) : s(s), t(t), z(-1) {}
    void o(int k)
    {
        int g = log10(z = k) + 1;
        x = g * (t - s + 1);
        v = 1ll * k * f[t - s + 1][g] % M;
    }
    void u();
    void d();
} b[200050 << 1];
void T::u()
{
    x = b[l].x + b[r].x;
    v = (b[l].v * p[b[r].x] + b[r].v) % M;
}
void T::d()
{
    if (~z)
        b[l].o(z), b[r].o(z), z = -1;
}
void B(int s, int t, int &p)
{
    b[p = ++c] = T(s, t);
    if (s == t)
        return (void)(scanf("%lld", &b[p].v), b[p].x = log10(b[p].v) + 1, b[p].v %= M);
    G;
    B(s, m, b[p].l);
    B(m + 1, t, b[p].r);
    b[p].u();
}
void C(int l, int r, int k, int p)
{
    if (l <= b[p].s && b[p].t <= r)
        return b[p].o(k);
    b[p].d();
    G;
    if (l <= m)
        C(l, r, k, b[p].l);
    if (r > m)
        C(l, r, k, b[p].r);
    b[p].u();
}
int Q(int l, int r, int p)
{
    if (l <= b[p].s && b[p].t <= r)
        return p;
    b[p].d();
    G;
    if (l <= m && r > m)
    {
        int t = ++c;
        b[t].l = Q(l, r, b[p].l);
        b[t].r = Q(l, r, b[p].r);
        b[t].u();
        return t;
    }
    if (l <= m)
        return Q(l, r, b[p].l);
    if (r > m)
        return Q(l, r, b[p].r);
}
int main()
{
    scanf("%d%d", &n, &m);
    for (int i = p[0] = 1; i <= n * 9; ++i)
        p[i] = p[i - 1] * 10ll % M;
    for (int i = 1; i <= n; ++i)
        for (int j = x = 1; j <= 9; ++j)
            f[i][j] = (f[i - 1][j] + (x = x * p[i - 1] % M)) % M;
    B(1, n, r);
    for (int i = 0, o, x, y, k; i < m; ++i)
    {
        scanf("%d%d%d", &o, &x, &y);
        if (o & 1)
            scanf("%d", &k), C(x, y, k, r);
        else
            k = c, printf("%lld\n", b[Q(x, y, r)].v), c = k;
    }
    return 0;
}

指针被卡了,哈哈。

数组开大 MLE 了好几发,哈哈。


赛后:板子,不评价。

绿,思维难度太低。

C

赛时:鉴定成功,验题人和审核的管理都不会点分治。

点分治套 01Trie,01Trie 上维护 $d_i$ 的最小值,直接做。

#include <cstdio>
#include <algorithm>
using namespace std;
struct E
{
    int v, w, x, t;
} e[400050];
struct T
{
    int c[2], v;
    T() : v(2e9) {}
} g[6000050];
int n, m, k, c, r = 1, R, P = 1, x[200050], d[200050], s[200050], p[200050], h[200050];
long long q = 2e9, w[200050];
bool b[200050];
void I(int d, int x)
{
    int p = r;
    for (int i = 30, o; i >= 0; --i)
        p = g[p].c[o = x >> i & 1] ? g[p].c[o] : g[p].c[o] = ++P, g[p].v = min(g[p].v, d);
}
int Q(int x)
{
    int p = r;
    int q = 2e9;
    for (int i = 30, o; i >= 0; --i)
    {
        if (!p)
            return q;
        o = !(x >> i & 1);
        if (k >> i & 1)
            p = g[p].c[o];
        else
            q = min(q, g[g[p].c[o]].v), p = g[p].c[!o];
    }
    if (!p)
        return q;
    return min(q, g[p].v);
}
void A(int u, int v, int w, int x)
{
    e[++c] = {v, w, x, h[u]};
    h[u] = c;
}
void X(int u, int k, int t)
{
    s[u] = 1;
    p[u] = 0;
    for (int i = h[u], v; i; i = e[i].t)
        if (!b[v = e[i].v] && v != k)
            X(v, u, t), s[u] += s[v], p[u] = max(p[u], s[v]);
    if (p[R] > (p[u] = max(p[u], t - s[u])))
        R = u;
}
void Y(int u, int k)
{
    d[++d[0]] = u;
    for (int i = h[u], v; i; i = e[i].t)
        if (!b[v = e[i].v] && v != k)
            w[v] = w[u] + e[i].w, x[v] = x[u] ^ e[i].x, Y(v, u);
}
void Q(int u, int k)
{
    b[u] = 1;
    I(0, 0);
    for (int i = h[u], v; i; i = e[i].t)
        if (!b[v = e[i].v] && v != k)
        {
            w[v] = e[i].w;
            x[v] = e[i].x;
            Y(v, u);
            for (int j = 1; j <= d[0]; ++j)
                q = min(q, w[d[j]] + Q(x[d[j]]));
            for (int j = 1; j <= d[0]; ++j)
                I(w[d[j]], x[d[j]]);
            d[0] = 0;
        }
    for (int i = 1; i <= P; ++i)
        g[i].c[0] = g[i].c[1] = 0, g[i].v = 2e9;
    r = P = 1;
    for (int i = h[u], v; i; i = e[i].t)
        if (!b[v = e[i].v] && v != k)
            p[R = 0] = 2e9, X(v, u, s[v]), X(R, 0, s[v]), Q(R, u);
}
int main()
{
    scanf("%d%d", &n, &k);
    for (int i = 1, u, v, w, x; i < n; ++i)
        scanf("%d%d%d%d", &u, &v, &w, &x), A(u, v, w, x), A(v, u, w, x);
    p[R = 0] = 2e9;
    X(1, 0, n);
    X(R, 0, n);
    Q(R, 0);
    return printf("%lld", q == 2e9 ? -1 : q), 0;
}

2e9 + 2e9 爆 int 了,哈哈。

指针又被卡了,哈哈。


赛后:原来出题人会点分治啊,但我觉得我的做法更高明,01 Trie 其实可以直接维护这个异或 $\ge k$。

紫,有出题人没想到的板子做法,建议加强验题力度。

D

赛时:数学题,不会做捏。

#include <cstdio>
#define M 998244353
int T, n, k, b;
long long x, y, z, q;
int main()
{
    scanf("%d", &T);
    while (T--)
    {
        scanf("%d%d%d", &n, &k, &b);
        x = b;
        y = z = q = 1;
        for (; k; k >>= 1, x = x * x % M)
            if (k & 1)
                y = y * x % M;
        for (int i = 0; i < n; ++i)
            q = q * (y + M - z) % M, z = z * b % M;
        printf("%lld\n", q);
    }
    return 0;
}

赛后:多项式能不能似一似啊。

不会做,不评价。


因为写 B 时连续脑抽,且中途发生了一些破事,提交时间跨度比较大。

不如叫补题记。

posted @ 2023-02-28 17:04  5k_sync_closer  阅读(10)  评论(0编辑  收藏  举报  来源