下笔春蚕食叶声。

Manthan, Codefest 18 (rated, Div. 1 + Div. 2) (E,F,G)

Link

E

m次操作,每次加边后询问最大旅行团。
旅行团的定义:旅行团中的每个人都至少有k个邻接点在团里。

显然会肯定很想全选,但是有的人压根没有k个邻接点,只能直接删掉,然后一直狂暴删点,删到最后就知道最大旅行团多大了。 但是这是 $O(n^2)$ 那么考虑倒着做,每次删边即可。

F

function z(array a, integer k):
    if length(a) < k:
        return 0
    else:
        b = empty array
        ans = 0
        for i = 0 .. (length(a) - k):
            temp = a[i]
            for j = i .. (i + k - 1):
                temp = max(temp, a[j])
            append temp to the end of b
            ans = ans + temp
        return ans + z(b, k)

给出 \(a,k\),求 \(z(a,k)\)

以下用 $[l,r]$ 表示 ${max}_{i=l}^r a_i$

考虑k=3的情况。

数组变化如下

\[[1,3],[2,4],[3,5]...\\ [1,5],[2,6],[3,7]...\\ [1,7]...\\ ...\\ [1,gap+1]...[n-gap,n] \]

也就是说 \(gap=r-l\) 的值是 \((k-1),2(k-1),...\)

枚举gap来计算是困难的,考虑 \(a_i\) 的贡献,\(a_i\) 向左连续不大于他的最左的是 \(a_l\),向右连续小于他的最右的是 \(a_r\)(为了防止相同的 \(a_i\) 干扰计算)

\(calc(l,r)\) 为区间 \(l,r\) 中会出现的区间个数,那么 \(a_i\) 贡献次数为 \(calc_{l,r}-calc_{l,i-1}-calc_{i+1,r}\),这个容易计算

G

vp写完F还有5min,然后pbb吹水去了。。看了半天题解。。

A和B玩游戏,二人轮流操作,A先手。

初始有一个字符串 \(s\),每次操作玩家可以选一个喜欢的字符 \(c\),把字符串 \(c\) 删掉,这样字符串就断开成多个,也就变成多个子游戏。不能操作者输。
xq93Ax.png

设字符 \(c\) 在字符串中出现位置为 \(a_1,a_2,...,a_k\)

会把一个字符串分割成上图那样。(绿色、红色部分内部没有字符 \(c\)

首先,子游戏SG值异或和是当前游戏的SG值(所以对于下图那个字符串的进行操作 \(c\) 后该状态的SG值就是绿色部分的异或和)

如果每次遇到询问都暴力求解SG函数值显然太慢了,我们发现有大量的重复计算部分。

那么可以dp预处理绿色部分(指对于每个 \(c\),每个绿色部分单独当成一个询问那样预处理),红色部分的数量是 \(O(26n)\) 级别的,可以记忆化。

对于每个字符 \(c\),对绿色部分做前缀和。然后就可以在 \(O(26n)\) 的复杂度内计算的所有询问的SG函数值。

具体实现可以看下代码,各数组的定义应该很容易得出(

那个SG值求mex的地方看着比较怪,官方题解是这么写的(暴露了我的补题写的和官方std差不多的事实),原因是你顶多 26​ 个后继,mex 取值肯定在 \([0,26]\) 内。

update:时间复杂度错了,是 \(O({26}^2n+26q)\)。是因为用dp_slow算红色部分的时间复杂度。考虑对于每个字符分26层(最多选26次字符就空了),每层的时间复杂度不超过 \(O(length)\)

const int N = 1e5 + 10, alf = 26;
char s[N]; int n, tmp[30], lst[30][N], nxt[30][N], dplst[30][N], dpnxt[30][N], dp[30][N], rk[N];
vector<int>vec[30];
vector<PII>seg;
bool cmp(PII x, PII y) { return x.se - x.fi < y.se - y.fi; }
int dp_slow(int l, int r) {
	int mask = 0;
	for(int c = 0; c < alf; c++) {
		int L = nxt[c][l], R = lst[c][r];
		if(L > r) continue;
		int ret = 0;
		for(int i = rk[L] + 1; i <= rk[R]; i++) ret ^= dp[c][i];
		if(l < L) {
			if(dpnxt[c][l] == -1) dpnxt[c][l] = dp_slow(l, L - 1);
			ret ^= dpnxt[c][l];
		}
		if(R < r) {
			if(dplst[c][r] == -1) dplst[c][r] = dp_slow(R + 1, r);
			ret ^= dplst[c][r];
		}
		if(ret < alf) mask |= (1 << ret);
	}
	for(int i = 0; i < alf; i++)
		if(!(mask & (1 << i))) return i;
	return alf;
}
int dp_fast(int l, int r) {
	int mask = 0;
	for(int c = 0; c < alf; c++) {
		int L = nxt[c][l], R = lst[c][r];
		if(L > r) continue;
		//cout<<"dp_fastw: "<<l<<" "<<r<<" "<<L<<" "<<R<<endl;
		int ret = (dp[c][rk[R]] ^ dp[c][rk[L]]);
		if(l < L) {
			if(dpnxt[c][l] == -1) dpnxt[c][l] = dp_fast(l, L - 1);
			ret ^= dpnxt[c][l];
		}
		if(R < r) {
			if(dplst[c][r] == -1) dplst[c][r] = dp_fast(R + 1, r);
			ret ^= dplst[c][r];
		}
		if(ret < alf) mask |= (1 << ret);
	}
	for(int i = 0; i < alf; i++)
		if(!(mask & (1 << i))) return i;
	return alf;
}
void init() {
	for(int i = 1; i <= n; i++) {
		int c = s[i] - 'a';
		if(vec[c].size()) seg.push_back(mkp(vec[c].back(), i));
		vec[c].push_back(i); rk[i] = vec[c].size() - 1;
	}
	
	for(int i = 0; i < alf; i++) tmp[i] = 0;
	for(int i = 1; i <= n; i++) {
		int c = s[i] - 'a'; tmp[c] = i;
		for(int j = 0; j < alf; j++)
			lst[j][i] = tmp[j];
	}
	
	for(int i = 0; i < alf; i++) tmp[i] = n + 1;
	for(int i = n; i >= 1; i--) {
		int c = s[i] - 'a'; tmp[c] = i;
		for(int j = 0; j < alf; j++)
			nxt[j][i] = tmp[j];
	}
	
	
	memset(dplst, -1, sizeof(dplst));
	memset(dpnxt, -1, sizeof(dpnxt));
	sort(seg.begin(), seg.end(), cmp);
	for(int i = 0; i < seg.size(); i++) {
		int l = seg[i].fi, r = seg[i].se;
		if(r - l == 1) continue;
		dp[s[r] - 'a'][rk[r]] = dp_slow(l + 1, r - 1);
	}
		
//	cout<<"??";
	for(int c = 0; c < alf; c++)
		for(int i = 1; i < vec[c].size(); i++)
			dp[c][i] ^= dp[c][i - 1];
	return;
}
int main() {
	scanf("%s", s + 1); n = strlen(s + 1);
	init();
	int m; scanf("%d", &m);
	while(m--) {
		int l, r; scanf("%d%d", &l, &r);
		if(dp_fast(l, r) == 0) puts("Bob");
		else puts("Alice");
	}
	return 0;
}
posted @ 2022-11-03 15:51  ACwisher  阅读(35)  评论(0编辑  收藏  举报