爆零力。

分析

T1

给定 $S=n^n,n\in\mathbb{N^{*}}$ $n$

用的 NTT,OJ 的评测机太慢了,常数爆炸。

正解是当 $n>2$ 时,每一个 $n^n$ 位数都不同,且等于 $\left\lfloor n\log_{10}n\right\rfloor + 1$ ,然后二分。

T2

动态,在给定点集中,找树的直径。

其中用到 $\mathcal{O}(1)$ LCA,方法是用欧拉序(DFS 序,但重复访问的点重复加入序里)转为序列,然后 ST 表求两点间深度最小的点。

贴个没过的代码:

const int N = 1e5 + 5;

inline ll Read() {
	ll x = 0, f = 1;
	char c = getchar();
	while (c != '-' && (c < '0' || c > '9')) c = getchar();
	if (c == '-') f = -f, c = getchar();
	while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar();
	return x * f;
}

int n, q;
int head[N], tot;
struct edge {
	int to, nxt;
}e[N << 1];
void Add(int u, int v) {
	e[++tot] = (edge) {v, head[u]}, head[u] = tot;
}
int dep[N], dfn, eln;
int a[N << 1], b[N], f[N][25];
int dpos[N], epos[N];
void dfs(int u, int fa) {
	dep[u] = dep[fa] + 1;
	f[u][0] = u;
	a[++eln] = u;
	b[++dfn] = u;
	dpos[u] = dfn;
	epos[u] = eln;
	for (int i = head[u]; i; i = e[i].nxt) {
		int v = e[i].to;
		if (v == fa) continue;
		dfs(v, u);
		a[++eln] = u;
	}
}

int LCA(int u, int v) {
	u = epos[u], v = epos[v];
	if (u > v) u ^= v ^= u ^= v;
	int len = log2(v - u + 1);
	if (dep[f[u][len]] < dep[f[v - (1 << len) + 1][len]]) return f[u][len];
	return f[v - (1 << len) + 1][len];
}
int distance (int u, int v) { return 2 * dep[LCA(u, v)] - dep[u] - dep[v]; }

int type[N];
struct SegmentTree {
	struct Tree {
		int l, r, p[2];
	}t[N << 2];

	void PushUp (int p) {
		int p1, p2, dis = 0, flag = 0;
		if (!type[t[p << 1].p[0]] && !type[t[p << 1].p[1]] && dis < distance(t[p << 1].p[0], t[p << 1].p[1])) dis = distance(t[p << 1].p[0], t[p << 1].p[1]), p1 = t[p << 1].p[0], p2 = t[p << 1].p[1], flag = 1;
		if (!type[t[p << 1 | 1].p[0]] && !type[t[p << 1].p[1]] && dis < distance(t[p << 1 | 1].p[0], t[p << 1].p[1])) dis = distance(t[p << 1 | 1].p[0], t[p << 1].p[1]), p1 = t[p << 1 | 1].p[0], p2 = t[p << 1].p[1], flag = 1;
		if (!type[t[p << 1 | 1].p[0]] && !type[t[p << 1].p[0]] && dis < distance(t[p << 1 | 1].p[0], t[p << 1].p[0])) dis = distance(t[p << 1 | 1].p[0], t[p << 1].p[0]), p1 = t[p << 1 | 1].p[0], p2 = t[p << 1].p[0], flag = 1;
		if (!type[t[p << 1].p[0]] && !type[t[p << 1 | 1].p[1]] && dis < distance(t[p << 1].p[0], t[p << 1 | 1].p[1])) dis = distance(t[p << 1].p[0], t[p << 1 | 1].p[1]), p1 = t[p << 1].p[0], p2 = t[p << 1 | 1].p[1], flag = 1;
		if (!type[t[p << 1].p[1]] && !type[t[p << 1 | 1].p[1]] && dis < distance(t[p << 1].p[1], t[p << 1 | 1].p[1])) dis = distance(t[p << 1].p[1], t[p << 1 | 1].p[1]), p1 = t[p << 1].p[1], p2 = t[p << 1 | 1].p[1], flag = 1;
		if (!type[t[p << 1 | 1].p[0]] && !type[t[p << 1 | 1].p[1]] && dis < distance(t[p << 1 | 1].p[0], t[p << 1 | 1].p[1])) 
			dis = distance(t[p << 1 | 1].p[0], t[p << 1 | 1].p[1]), p1 = t[p << 1 | 1].p[0], p2 = t[p << 1 | 1].p[1], flag = 1;
		if (!flag) {
			if (!type[t[p << 1].p[0]]) p1 = p2 = t[p << 1].p[0], flag = 1;
			if (!type[t[p << 1].p[1]]) p1 = p2 = t[p << 1].p[1], flag = 1;
			if (!type[t[p << 1 | 1].p[0]]) p1 = p2 = t[p << 1 | 1].p[0], flag = 1;
			if (!type[t[p << 1 | 1].p[1]]) p1 = p2 = t[p << 1 | 1].p[1], flag = 1;
		} 
		if (!flag) p1 = p2 = t[p << 1].p[0];
		t[p].p[0] = p1, t[p].p[1] = p2;
	}
	void Build(int p, int l, int r) {
		t[p].l = l, t[p].r = r;
		if (t[p].l == t[p].r) {
			t[p].p[0] = t[p].p[1] = b[t[p].l];
			return;
		}
		int mid = t[p].l + t[p].r >> 1;
		Build (p << 1, l, mid);
		Build (p << 1 | 1, mid + 1, r);
		PushUp(p);
	}
	void Modify(int p, int x) {
		if (t[p].l == t[p].r) {
			type[x] ^= 1;
			return;
		}
		int mid = t[p].l + t[p].r >> 1;
		if (x <= mid) Modify (p << 1, x);
		else Modify (p << 1 | 1, x);
		PushUp(p);
	}
}t;

int main() {
//	freopen(".in", "r", stdin);
//	freopen(".out", "w", stdout);
	n = Read(), q = Read();
	for (int i = 1; i < n; i++) {
		int u = Read(), v = Read();
		Add(u, v), Add(v, u);
	}
	dfs(1, 0);
	for (int j = 1; j <= 22; j++)
		for (int i = 1; i + (1 << j) <= eln; i++)
			if (dep[f[i][j-1]] < dep[f[i + (1 << j - 1)][j-1]]) f[i][j] = f[i][j-1];
			else f[i][j] = f[i + (1 << j-1)][j-1];
	t.Build(1, 1, n);
//	return 0;
	for (; q--; ) {
		string s;
		cin >> s;
		if (s[0] == 'G') {
			printf ("%d\n", distance(t.t[1].p[0], t.t[1].p[1]));
		} else {
			int x = Read();
			t.Modify(1, b[x]);
		}
	}
	return 0;
}
EOF

评论

暂无评论

发表评论

可以用@mike来提到mike这个用户,mike会被高亮显示。如果你真的想打“@”这个字符,请用“@@”。

博客信息

作者
Jayun
时间
2022-11-15 07:28:12
博客类型