如题,蒟蒻只通过了样例,全部 WA + 2点TLE
求大佬提供一组 hack 数据,或帮助我找出 bug 所在,先行感谢。
#include <bits/extc++.h>
// #define inline __always_inline
#define inline
#define virt(x) ((x) + stack)
#define real(x) ((x) - stack)
const uint16_t mod = 10007;
uint16_t inv[10008];
int poly_size;
template <typename T>
inline void read(T &x)
{
char ch;
for (ch = getchar(); !isdigit(ch); ch = getchar());
for (x = 0; isdigit(ch); ch = getchar())
x = x * 10 + ch - '0';
}
inline void read(char &ch)
{
for (ch = getchar(); !isupper(ch); ch = getchar());
}
class poly_ex_t;
class poly_t
{
public:
uint16_t x[128];
poly_t(uint16_t fill) { for (int i = 0; i < 128; i++) x[i] = fill; }
poly_t(const poly_ex_t &poly);
poly_t() {}
inline uint16_t &operator[](int pos) { return x[pos]; }
inline const uint16_t &operator[](int pos) const { return x[pos]; }
inline void operator+=(const poly_t &p)
{
for (int i = 0; i < poly_size; i++)
x[i] = (x[i] + p[i]) % mod;
}
inline void operator-=(const poly_t &p)
{
for (int i = 0; i < poly_size; i++)
x[i] = (x[i] + mod - p[i]) % mod;
}
inline void operator*=(const poly_t &p)
{
for (int i = 0; i < poly_size; i++)
x[i] = (uint32_t)x[i] * p[i] % mod;
}
inline poly_t operator+(const poly_t &p) const
{
poly_t ans;
for (int i = 0; i < poly_size; i++)
ans[i] = (x[i] + p[i]) % mod;
return ans;
}
inline poly_t operator*(const poly_t &p) const
{
poly_t ans;
for (int i = 0; i < poly_size; i++)
ans[i] = (uint32_t)x[i] * p[i] % mod;
return ans;
}
inline void FWT(uint16_t type = 1)
{
for (int half = 1, step = 2; step <= poly_size; half <<= 1, step <<= 1)
for (int base = 0; base < poly_size; base += step)
for (int i = 0; i < half; i++)
{
uint16_t a = x[base + i], b = x[base + i + half];
x[base + i] = (uint32_t)(a + b) * type % mod;
x[base + i + half] = (uint32_t)(a - b + mod) * type % mod;
}
}
inline void debug()
{
for (int i = 0; i < poly_size; i++)
printf("%d ", x[i]);
putchar('\n');
}
};
poly_t poly_unit(1), poly_null;
class poly_ex_t : public poly_t
{
public:
uint16_t count[128];
inline void operator*=(const poly_t &p)
{
for (int i = 0; i < poly_size; i++)
{
assert(p[i] < mod);
if (p[i])
x[i] = (uint32_t)x[i] * p[i] % mod;
else
count[i]++;
}
}
inline void operator/=(const poly_t &p) // ! bug: inv[p[i]] might be undefined
{
for (int i = 0; i < poly_size; i++)
{
if (inv[p[i]])
x[i] = (uint32_t)x[i] * inv[p[i]] % mod;
else
count[i]--;
}
}
};
poly_t::poly_t(const poly_ex_t &poly)
{
for (int i = 0; i < 128; i++)
{
if (poly.count[i])
x[i] = 0;
else
x[i] = poly.x[i];
}
}
struct vector_t { poly_t x, y, z; };
struct matrix_t
{
poly_t a, b, c, d;
inline matrix_t operator*(const matrix_t &m)
{
return (matrix_t){a * m.a, a * m.b + b, a * m.c + c, c * m.b + d + m.d};
}
inline vector_t operator*(const vector_t &v)
{
return (vector_t){a * v.x + b * v.z, c * v.x + v.y + d * v.z, v.z};
}
inline void debug()
{
a.debug();
b.debug();
c.debug();
d.debug();
}
};
matrix_t matrix_unit = {poly_unit, poly_null, poly_null, poly_null};
struct node_t
{
node_t *parent, *head;
node_t *hson, *tail;
int size, start;
};
node_t stack[30001];
std::vector<node_t *> graph[30001];
void build(node_t *u = virt(1))
{
u->size = 1;
u->hson = virt(0);
for (auto &&v : graph[real(u)])
{
if (v == u->parent)
continue;
v->parent = u;
build(v);
u->size += v->size;
if (u->hson->size < v->size)
u->hson = v;
}
}
int timestamp = 0;
void decomposition(node_t *u = virt(1), node_t *head = virt(1))
{
u->start = timestamp++;
u->head = head;
if (u->hson != virt(0))
decomposition(u->hson, head), u->tail = u->hson->tail;
else
u->tail = u;
for (auto &&v : graph[real(u)])
if (v != u->parent && v != u->hson)
decomposition(v, v);
}
class segment_tree_t
{
public:
struct segment_t
{
int l, r;
inline int size() const { return r - l; }
inline int mid() const { return l + r >> 1; }
inline segment_t left() const { return {l, mid()}; }
inline segment_t right() const { return {mid(), r}; }
inline bool in(const segment_t &s) const { return s.l <= l && r <= s.r; }
inline bool out(const segment_t &s) const { return s.r <= l || r <= s.l; }
inline bool in(int pos) const { return pos == l && r == pos + 1; }
inline bool out(int pos) const { return pos < l || r <= pos; }
};
struct node_t
{
node_t *left, *right;
segment_t s;
matrix_t m;
};
node_t *stack, *top, *root;
segment_tree_t(int size) { stack = top = root = (node_t *)calloc(size, sizeof(node_t)); }
~segment_tree_t() { free(stack); }
inline void push_up(node_t *u) { u->m = u->left->m * u->right->m; }
void build(node_t *u, const segment_t &s, matrix_t *m)
{
u->s = s;
if (s.size() == 1)
u->m = m[s.l];
else
build(u->left = ++top, s.left(), m), build(u->right = ++top, s.right(), m), push_up(u);
}
matrix_t prod(node_t *u, const segment_t &s)
{
if (u->s.out(s))
return matrix_unit;
if (u->s.in(s))
return u->m;
return prod(u->left, s) * prod(u->right, s);
}
void set(node_t *u, int pos, matrix_t m)
{
if (u->s.out(pos))
return;
if (u->s.in(pos))
u->m = m;
else
set(u->left, pos, m), set(u->right, pos, m), push_up(u);
}
};
int n, q, u, v;
char op;
uint16_t w[30001];
segment_tree_t tree(60000);
poly_t A[30000], C[30000], D[30000];
poly_ex_t B[30000];
matrix_t mat[30000];
void init_A(node_t *u = virt(1))
{
A[u->start][w[real(u)]] = 1;
A[u->start].FWT();
for (auto &&v : graph[real(u)])
{
if (v == u->parent)
continue;
init_A(v);
A[u->start] *= (A[v->start] + poly_unit);
}
}
void init_B(node_t *u = virt(1))
{
B[u->start][w[real(u)]] = 1;
B[u->start].FWT();
for (auto &&v : graph[real(u)])
{
if (v == u->parent)
continue;
init_B(v);
if (v != u->hson)
B[u->start] *= A[v->start] + poly_unit;
}
}
void init_C(node_t *u = virt(1))
{
C[u->start] = A[u->start];
for (auto &&v : graph[real(u)])
{
if (v == u->parent)
continue;
init_C(v);
C[u->start] += C[v->start];
}
}
void init_D()
{
for (node_t *u = virt(1); u <= virt(n); u++)
for (auto &&v : graph[real(u)])
if (v != u->parent && v != u->hson)
D[u->start] += C[v->start];
}
void debug()
{
printf("B:\n");
for (int i = 0; i < timestamp; i++)
{
poly_t tmp(B[i]);
tmp.debug();
}
printf("D:\n");
for (int i = 0; i < timestamp; i++)
D[i].debug();
for (int i = 0; i < timestamp; i++)
mat[i] = tree.prod(tree.root, {i, i + 1});
printf("Matrix:\n");
for (int i = 0; i < timestamp; i++)
printf("%d>\n", i), mat[i].debug();
}
void init_matrix()
{
for (int i = 0; i < timestamp; i++)
{
poly_t B_poly(B[i]);
mat[i] = {B_poly, B_poly, B_poly, D[i] + B_poly};
}
tree.build(tree.root, {0, timestamp}, mat);
}
void init_inv()
{
inv[1] = 1;
for (int i = 2; i < mod; i++)
inv[i] = (uint32_t)(mod - mod / i) * inv[mod % i] % mod;
}
inline vector_t query(node_t *u, int k)
{
node_t *tail = u->tail;
vector_t ans = {A[tail->start], C[tail->start], poly_unit};
matrix_t total = tree.prod(tree.root, {u->start, tail->start});
return total * ans;
}
void modify(node_t *u, int k)
{
poly_t origin = poly_null, now = poly_null;
origin[w[real(u)]] = 1, now[w[real(u)] = k] = 1;
origin.FWT(); now.FWT();
B[u->start] /= origin;
B[u->start] *= now;
while (u->head->parent)
{
node_t *next = u->head->parent;
vector_t ans = query(u->head, k);
D[next->start] -= ans.y;
B[next->start] /= ans.x + poly_unit;
poly_t B_poly(B[u->start]);
tree.set(tree.root, u->start, {B_poly, B_poly, B_poly, D[u->start] + B_poly});
if (u == u->tail)
C[u->start] = A[u->start] = B_poly;
ans = query(u->head, k);
D[next->start] += ans.y;
B[next->start] *= ans.x + poly_unit;
u = next;
}
poly_t B_poly(B[u->start]);
if (u == u->tail)
C[u->start] = A[u->start] = B_poly;
tree.set(tree.root, u->start, {B_poly, B_poly, B_poly, D[u->start] + B_poly});
}
int main()
{
init_inv();
read(n), read(poly_size);
for (int i = 1; i <= n; i++)
read(w[i]);
for (int i = 1; i < n; i++)
{
read(u), read(v);
graph[u].push_back(virt(v));
graph[v].push_back(virt(u));
}
build();
decomposition();
init_A();
init_B();
init_C();
init_D();
init_matrix();
// debug();
read(q);
for (int i = 0; i < q; i++)
{
read(op);
if (op == 'Q')
{
read(u);
auto ans = query(virt(1), u);
ans.y.FWT(inv[2]);
printf("%hu\n", ans.y[u]);
}
else
{
read(u), read(v);
modify(virt(u), v);
}
}
// debug();
return 0;
}