WA求调(有注释)
查看原帖
WA求调(有注释)
766573
chenbs楼主2024/11/1 23:59

用的是 lsj2009 那篇题解的思路,时间复杂度带一个 log。不知道为什么就 WA 了

#include<bits/stdc++.h>
using namespace std;
int n, m, k, nown, a[400005], a2[400005], c[400005];
char s[20][400005];
struct node {
	int d; // 擂主
	int g; // 这个节点是第几场比赛

	int w; // 自由选手能力值为 inf 时的 winner
	int maxn; // 想让一个自由选手成为 winner,n' 最大是多少
} t[400005];
int pos[400005]; // 每个人对应的节点
int cnt[20];
void init(int u, int dep) {
	++cnt[dep];
	if(dep==k) {
		pos[cnt[dep]]=u;
		t[u].g = cnt[dep];
		return;
	}
	t[u].d = s[dep][cnt[dep]]^48;
	init(u<<1, dep+1), init(u<<1|1, dep+1);
}
void dfs(int u, int dep) {
	if(dep==k) {
		t[u].w=t[u].g, t[u].maxn=t[u].g-1;
		return;
	}
	dfs(u<<1, dep+1), dfs(u<<1|1, dep+1);
	int s1=u<<1|(t[u].d), s2=s1^1;
	// s1 为当擂主的儿子,s2 为另一个儿子
	if(a[t[s1].w] >= k-dep) t[u].w=t[s1].w, t[u].maxn=t[s1].maxn;
	else t[u].w=t[s2].w, t[u].maxn=t[s2].maxn;
	t[u].maxn=max(t[u].maxn, t[s1].maxn);
}
int ans[400005];
void add(int l, int r, int val) { // 区间加
	if(l<=r) ans[l]+=val, ans[min(r, nown)+1]-=val;
}
void calc() {
	nown=1<<k;
	for(int i=0; i<=nown; i++) ans[i]=0;
	for(int i=n+1; i<=nown; i++) a[i]=1e9; // 自由选手能力无穷大
	dfs(1, 0);
	add(1, 1, 1);
	for(int i=1; i<=nown; i++) {
		int u=pos[i], dep=0, val=1e9;
		// 分析普通选手
		if(i<=n) {
			while(u>1) {
				int f=u>>1;
				++dep;
				if((u&1) == t[f].d) {
					if(a[i]<dep) break;
				} else {
					if(a[t[u^1].w] >= dep) {
						// 被普通选手干掉了,所以只能把希望寄托在自由选手身上了
						val=min(val, t[u^1].maxn);
					}
				}
				if(i <= (1<<dep)) {
					add(max((1<<(dep-1))+1, i), min(val, 1<<dep), i);
				}
				u=f;
			}
		}
		// 分析自由选手
		u=pos[i], dep=0, val=1e9;
		while(u>1) {
			int f=u>>1;
			++dep;
			if((u&1) != t[f].d) {
				if(a[t[u^1].w] >= dep) {
					val=min(val, t[u^1].maxn);
				}
			}
			if(i <= (1<<dep)) {
				add((1<<(dep-1))+1, min(val, i-1), i);
				break;
			}
			u=f;
		}
	}
	for(int i=1; i<=nown; i++) ans[i]+=ans[i-1];
}
int main() {
	scanf("%d%d", &n, &m);
	for(int i=1; i<=n; i++) scanf("%d", &a2[i]);
	for(int i=1; i<=m; i++) scanf("%d", &c[i]);
	while((1<<k) < n) k++;
	for(int i=k-1; i>=0; i--) scanf("%s", s[i]+1);
	init(1, 0);

	int T;
	scanf("%d", &T);
	while(T--) {
		int x[4];
		scanf("%d%d%d%d", x, x+1, x+2, x+3);
		for(int i=1; i<=n; i++) a[i]=a2[i]^x[i&3];
		calc();
		long long r=0;
		for(int i=1; i<=m; i++) r^=i*ans[c[i]];
		printf("%d\n", r);
	}
	return 0;
}
2024/11/1 23:59
加载中...