제출 #1158455

#제출 시각아이디문제언어결과실행 시간메모리
1158455sleepntsheepLampice (COCI19_lampice)C11
73 / 110
5096 ms326948 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 Base = 137;
int n, *eh[N], eo[N], Z[N + N], Z_, sz[N], answer = 1, mode, len, t1[N * 2], t2[N * 2], bp[1 + N], bpi[1 + N]
	, ii, A[N*17], L[N*17], R[N*17], B[N*17];
unsigned seed;
unsigned char dead[N];
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;
}

void zer(int *t, int p) {
	p += n;
	for (t[p] = 0; p /= 2;)
		t[p] = 0;
}

void upd2(int *t, int p, int k) {
	for (t[p += n] = k % M; p /= 2;)
		t[p] = (t[p * 2] + t[p * 2 + 1]) % M;
}

int qry2(int *t, int l, int r) {
	int z = 0;
	for (l += n, r += n + 1; l < r; l /= 2, r /= 2) {
		if (l & 1) z = (z + t[l++]) % M;
		if (r & 1) z = (t[--r] + z) % M;
	}
	return z;
}

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, mset_short, mset_equal;

void mset_insert(Hash *v, int k) {
	v[0][k >> 5] |= 1 << (k & 31);
}

void mset_unset(Hash *v, int k) {
	v[0][k >> 5] = 0;
}

int mset_count(Hash *v, int k) {
	return (v[0][k >> 5] >> (k & 31)) & 1;
}

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

int qry(int *t, int l, int r) {
	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);

	if (mode == EVEN) {
		if (update) {
			if (dep * 2 < len) {
				mset_insert(&mset_short, qry(t1, 0, dep));
			} else {
				int y = len - dep;
				int x = (dep - y) / 2;

				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(&mset, qry(t1, 2 * x + 1, dep) * 1ll * bpi[2 * x + 1] % M);
					fprintf(stderr, " g1: insert %d\n", qry(t1, 2 * x + 1, dep) * 1ll * bpi[2 * x + 1] % M);
				}
				else if (y == 1) {
					if ((s[u] - 'Z') == qry(t1, 0, 0)) {
						++has;
						if(has)fprintf(stderr, "e1: get %d at %d, x = %d\n", len, u, x);
					}
				}
			}
		} else {
			if (dep * 2 < len) {
				fprintf(stderr, " g2: count %d = %d\n", qry(t1,0,dep),mset_count(&mset,qry(t1,0,dep)));
					has += mset_count(&mset, qry(t1, 0, dep));
				if (has)fprintf(stderr, "e3: get %d at %d\n", len, u);
			} else {
				int y = len - dep;
				int x = (dep - y) / 2;

				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(&mset_short, qry(t1, 2 * x + 1, dep) * 1ll * bpi[2 * x + 1] % M);
					if(has)fprintf(stderr, "e2: get %d at %d\n", len, u);
				}
			}
		}
	} else if (mode == ODD) {
		if (update) {
			if (dep * 2 + 1 == len) {
				mset_insert(&mset_equal, qry(t1, 0, dep));
				fprintf(stderr, "Ins %d\n", qry(t1, 0, dep));
			} else if (dep * 2 < len) {
				mset_insert(&mset_short, qry(t1, 0, dep));
			} else {
				int y = len - dep;
				int x = (dep - y) / 2;

				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(&mset, 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(&mset_equal, qry(t1, 0, dep));
				fprintf(stderr, "Cnt %d\n", qry(t1, 0, dep));
			} else if (dep * 2 < len) {
				has += mset_count(&mset, qry(t1, 0, dep));
			} else {
				int y = len - dep;
				int x = (dep - y) / 2;

				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(&mset_short, 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 efs_clear(int u, int p, int dep) {
	if (dep >= len)
		return;

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

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

	if (mode == EVEN) {
		if (dep * 2 < len)
			mset_unset(&mset_short, qry(t1, 0, dep));
		else
			mset_unset(&mset, qry(t1, 2 * x + 1, dep) * 1ll * bpi[2 * x + 1] % M);
	} else if (mode == ODD) {
		if (dep * 2 + 1 == len)
			mset_unset(&mset_equal, qry(t1, 0, dep));
		else if (dep * 2 < len)
			mset_unset(&mset_short, qry(t1, 0, dep));
		else
			mset_unset(&mset, 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_clear(*v, u, 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' ) % M);
	upd(t2, 0, (s[u] - 'Z' ) * 1ll * bp[N - 0] % M);

	fprintf(stderr, "f1: centroid = %d\n", u);

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

	for (int *v = eh[u]; eh[u] + eo[u] > v; ++v)
		efs_clear(*v, 0, 1);

	/* 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;
		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;
}

컴파일 시 표준 에러 (stderr) 메시지

lampice.c: In function 'init':
lampice.c:59:9: warning: ignoring return value of 'scanf' declared with attribute 'warn_unused_result' [-Wunused-result]
   59 |         scanf("%d%s", &n, s + 1);
      |         ^~~~~~~~~~~~~~~~~~~~~~~~
lampice.c:62:17: warning: ignoring return value of 'scanf' declared with attribute 'warn_unused_result' [-Wunused-result]
   62 |                 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...