线性做法被卡常求助
查看原帖
线性做法被卡常求助
760824
MornStar楼主2024/10/31 22:17

RT,TLE92

#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const int N=1e5+5,K=(1<<17)+5;
int n,m,A[N],a[N],c[N];
int k,leaf[K];
int T,x[4];
bool d[N<<1];
int f[N<<2],g[N<<2],h[N<<2],b[N<<2];
ll sum[N],res[N];
int M,C;
#ifdef ONLINE_JUNGE

#define getchar() getchar_unlocked()

#endif
template<typename T>
void read(T& x){
	char ch=getchar();x=0;
	while(!isdigit(ch))	ch=getchar();
	while(isdigit(ch))	x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
}
void read_bool(bool& x){
	char ch=getchar();x=0;
	while(!isdigit(ch))	ch=getchar();
	x=ch^48;
}
void dfs(int x,int t){
	f[x]=-1,g[x]=t+1;
	if(x>=M)	return;
	int to=(x<<1)^d[x];
	h[to]=h[to^1]=h[x]-1;
	if(b[x])	b[to]=b[to^1]=b[x];
	else	b[to]=h[x],b[to^1]=0;
	dfs(to,t);dfs(to^1,t);
}
void upd(int x,int t){
	if(!x||f[x]!=-1)	return;
	int to=(x<<1)^d[x];
	if(f[to]>=h[x])	f[x]=f[to],g[to^1]=min(g[to^1],t);
	else if(f[to]!=-1)	f[x]=f[to^1];
	if(f[x]!=-1)	upd(x>>1,t);//x->fa x>>1
}
void get_g(int x){
	if(g[x]<=(C>>1))	return;
	if(x>=M)	return sum[g[x]-1]+=x-M+1,void();
	int to=x<<1;
	g[to]=min(g[to],g[x]);get_g(to);
	g[to^1]=min(g[to^1],g[x]);get_g(to^1);
}
void solve(int x){
	C=(1<<x);
	int rt=1<<(k-x);
	h[rt]=x,b[rt]=0;
	dfs(rt,C);
	for(int i=1;i<=min(C,n);i++){
		if(a[i]<b[leaf[i]])	g[leaf[i]]=min(g[leaf[i]],i);
		f[leaf[i]]=a[i];
		upd(leaf[i]>>1,i);
	}
	for(int i=(C>>1);i<=C;i++)	sum[i]=0;
	get_g(rt);
	for(int i=C;i>=(C>>1);i--)	sum[i-1]+=sum[i],res[i]=sum[i];
}
int main(){
	read(n),read(m);
	for(int i=1;i<=n;i++)	read(A[i]);
	for(int i=1;i<=m;i++)	read(c[i]);
	while((1<<k)<n)	k++;M=1<<k;
	for(int i=1;i<=M;i++)	leaf[i]=M+i-1;
	for(int i=k-1;i>=0;i--){
		for(int j=0;j<(1<<i);j++)	read_bool(d[(1<<i)+j]);
	}
	for(int i=1;i<=M;i++)	leaf[i]=M+i-1;
	read(T);
	while(T--){
		read(x[0]);read(x[1]);read(x[2]);read(x[3]);
		for(int i=1;i<=n;i+=4){
			a[i]=A[i]^x[1];
			if(i+1<=n)	a[i+1]=A[i+1]^x[2];
			if(i+2<=n)	a[i+2]=A[i+2]^x[3];
			if(i+3<=n)	a[i+3]=A[i+3]^x[0];
		}
		for(int i=k;i>=0;i--)	solve(i);
		ll ans=0;
		for(int i=1;i<=m;i++)	ans^=(i*res[c[i]]);
		printf("%lld\n",ans);
	}
}
2024/10/31 22:17
加载中...