Submission #1160524

#TimeUsernameProblemLanguageResultExecution timeMemory
1160524sleepntsheepLampice (COCI19_lampice)C++20
110 / 110
2277 ms244296 KiB
#pragma GCC optimize("O3,unroll-loops")

#include <stdio.h>
#include <string.h>

#define N (50005)
#define M 1000000007

#define fprintf(...) 42
#define EVEN 0x1
#define ODD 0x3

int dead[N], Base = 137, n, *eh[N], eo[N], Z[N + N], Z_, sz[N], answer = 1, mode, len, t1[N], t2[N], bp[1 + N], bpi[1 + N], ii, sentinel;
unsigned seed;

char s[N];

int bpow(int a, int b) {
	if (!b) return 1;
	int r = bpow(a, b / 2);
	if (b & 1) return r * 1ll * r % M * a % M;
	return r * 1ll * r %M;
}

int *rizz(int n) {
	return Z + (Z_ += n) - n;
}

void init() {
	bp[0] = 1;
	for (int i = 1; i <= N; ++i)
		bp[i] = bp[i - 1] * 1ll * Base % M;
	for (int i = 0; i <= N; ++i)
		bpi[i] = bpow(bp[i], M - 2);

	static int u[N], v[N];
	scanf("%d%s", &n, s + 1);

	for (int i = 1; i < n; ++i) {
		scanf("%d%d", &u[i], &v[i]);
		++eo[u[i]]; ++eo[v[i]];
	}

	for (int i = 1; i <= n; ++i) {
		eh[i] = rizz(eo[i]);
		eo[i] = 0;
	}

	for (int i = 1; i < n; ++i) {
		eh[u[i]][eo[u[i]]++] = v[i];
		eh[v[i]][eo[v[i]]++] = u[i];
	}
}

void dfs(int u, int p) {
	sz[u] = 1;
	for (int *v = eh[u]; eh[u] + eo[u] > v; ++v)
		if (! dead[*v] && *v != p)
			dfs(*v, u), sz[u] += sz[*v];
}

int get_centroid(int u, int p, int tsz) {
	for (int *v = eh[u]; eh[u] + eo[u] > v; ++v)
		if (! dead[*v] && *v != p && 2 * sz[*v] >= tsz)
			return get_centroid(*v, u, tsz);
	return u;
}

void centroid_reset() {
	memset(dead, 0, sizeof dead);
	ii = 0;
}

typedef unsigned Hash[31999999];

int has;
Hash mset[2];

int rrrr[2999999], records[2999999], ro;

void mset_insert(int o, int k) {
	++ro;
	rrrr[ro] = o;
	records[ro] = k >> 5;
	mset[o][k >> 5] |= 1 << (k & 31);
}

void mset_clear() {
	while (ro)
	{
		mset[rrrr[ro]][records[ro]] = 0;
		--ro;
	}
}

int mset_count(int o, int k) {
	return (mset[o][k >> 5] >> (k & 31)) & 1;
}

void upd(int *t, int p, int k) {
	if (p)
		t[p] = (t[p - 1] + k) % M;
	else
		t[p] = k % M;
}

int qry(int *t, int l, int r) {
	if (l > r)
		return 0;
	if (l)
		return (t[r] + (M - t[l - 1]) % M) % M;
	return t[r];
}

void efs(int u, int p, int update, int dep) {
	if (dep >= len)
		return;

	upd(t1, dep, (s[u] - 'Z' ) * 1ll * bp[dep] % M);
	upd(t2, dep, (s[u] - 'Z' ) * 1ll * bp[N - dep] % M);

	int y = len - dep;
	int x = (dep - y) / 2;

	if (mode == EVEN) {
		if (update) {
			if (dep * 2 < len) {
				mset_insert(1, qry(t1, 0, dep));
			} else {
				if (x > 0 && qry(t1, 1, x) * 1ll * bpi[1] % M 
						!= qry(t2, x + 1, 2 * x) * 1ll *  bpi[N - 2 * x] % M) {
				}
				else if (y > 1) {
					mset_insert(0, qry(t1, 2 * x + 1, dep) * 1ll * bpi[2 * x + 1] % M);
				}
				else if ((s[u] - 'Z') == qry(t1, 0, 0))
					++has;
			}
		} else {
			if (dep * 2 < len) {
					has += mset_count(0, qry(t1, 0, dep));
			} else {

				if (qry(t1, 1, x) * 1ll * bpi[1] % M 
						!= qry(t2, x + 1, 2 * x) * 1ll *  bpi[N - 2 * x] % M) {

				} else if (y > 1) {
					has += mset_count(1, qry(t1, 2 * x + 1, dep) * 1ll * bpi[2 * x + 1] % M);
				}
			}
		}
	} else if (mode == ODD) {
		if (update) {
			if (dep * 2 + 1 == len) {
				mset_insert(0, qry(t1, 0, dep));
			} else if (dep * 2 < len) {
				mset_insert(1, qry(t1, 0, dep));
			} else {

				if (x > 0 && qry(t1, 1, x) * 1ll * bpi[1] % M 
						!= qry(t2, x + 2, x + 2 + x - 1) * 1ll * bpi[N - 2 * x - 1] % M) {
				}
				else if (y > 1) {
					mset_insert(0, qry(t1, 2 * x + 2, dep) * 1ll * bpi[2 * x + 2] % M);
				}
				else
					if (s[u] - 'Z' == qry(t1, 0, 0)) {
						++has;
					}
			}
		} else {
			if (dep * 2 + 1 == len) {
				has += mset_count(0, qry(t1, 0, dep));
			} else if (dep * 2 < len) {
				has += mset_count(0, qry(t1, 0, dep));
			} else {
				if (qry(t1, 1, x) * 1ll * bpi[1] % M 
						!= qry(t2, x + 2, x + 2 + x - 1) * 1ll *  bpi[N - 2 * x - 1] % M) {
				}
				else if (y > 1) {
					has += mset_count(1, qry(t1, 2 * x + 2, dep) * 1ll * bpi[2 * x + 2] % M);
				}
			}
		}
	}


	for (int *v = eh[u]; eh[u] + eo[u] > v; ++v)
		if (! dead[*v] && *v != p)
			efs(*v, u, update, dep + 1);
}

void centroid_decomposition(int u, int dep, int par) {
	dfs(u, u);
	u = get_centroid(u, u, sz[u]);
	dead[u] = 1;

	/* process */
	upd(t1, 0, s[u] - 'Z');
	upd(t2, 0, (s[u] - 'Z' ) * 1ll * bp[N - 0] % M);

	for (int *v = eh[u]; eh[u] + eo[u] > v; ++v) 
		if (! dead[*v]) {
			efs(*v, 0, 0, 1);
			efs(*v, 0, 1, 1);
		}

	mset_clear();

	/* decomp */
	for (int *v = eh[u]; eh[u] + eo[u] > v; ++v)
		if (! dead[*v])
			centroid_decomposition(*v, dep + 1, u);
}

void find_even() {
	mode = EVEN;

	int lower = 0, upper = n / 2 + 1;
	while (upper - lower > 1) {
		int mid = lower + (upper - lower) / 2;
		len = mid * 2;

		has = 0;
		centroid_reset();
		centroid_decomposition(1, 0, 0);

		if (has)
			lower = mid;
		else
			upper = mid;
	}
	if (answer < lower * 2)
		answer = lower * 2;
}

void find_odd() {
	mode = ODD;

	int lower = 1, upper = (n + 1) / 2 + 1;
	while (upper - lower > 1) {
		int mid = lower + (upper - lower) / 2;
		len = mid * 2 - 1;

		has = 0;
		if (len <= answer)
			has = 1;
		else {
			centroid_reset();
			centroid_decomposition(1, 0, 0);
		}

		if (has)
			lower = mid;
		else
			upper = mid;
	}

	if (answer < lower * 2 - 1)
		answer = lower * 2 - 1;
}

int main() {
	init();
	find_even();
	find_odd();

	printf("%d\n", answer);

	return 0;
}

Compilation message (stderr)

lampice.cpp: In function 'void init()':
lampice.cpp:37:14: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
   37 |         scanf("%d%s", &n, s + 1);
      |         ~~~~~^~~~~~~~~~~~~~~~~~~
lampice.cpp:40:22: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
   40 |                 scanf("%d%d", &u[i], &v[i]);
      |                 ~~~~~^~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...