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 时连续脑抽,且中途发生了一些破事,提交时间跨度比较大。
不如叫补题记。