題目
思路
cjr Orz
設\(f_i\)表示第一個到\(i\)的人是否必勝,對於詢問\([l,r]\),可以發現\(f_r\)只與\(a_r\)的奇偶性有關,奇數為1偶數為0
如果\(f_i=1\),那么\(i\)向前\(m\)位都有\(f_j=0\),對於點\(i-m-1\),如果有人到這里無路可走,他就必須向后走,一定會落到這\(m\)個位置之一中,即必輸,所以\(f_{i-m-1}\)的勝負也只與\(a_{i-m-1}\)的奇偶性有關
如果\(f_i=0\),考慮\(f_{i-1}\),如果\(a_{i-1}\)為偶數,假設\(B_{i-1}=2\)去試,如果A走進來,那么B可以不走出去,那么只能A走出去,但是后面能到達的點一定都是0(否則為什么\(f_i\)會為0),所以\(f_{i-1}=0\),奇數亦然;綜上,\(f_{i-1}\)的勝負與\(a_{i-1}\)奇偶性相關
將\(i\)作為右邊界時,用上面兩項可以推出此時它前面有哪些為1,將它和最近的1連邊,沒有就向0節點連邊,每個點都會向前面一個點連邊,顯然會構成一個樹形結構,一個點只有父親節點都是必勝節點
判斷\([l,r]\)是否必勝,等價於判斷\(l\)是不是\(r\)的父親,用dfs序即可,注意特判\(l==r\)
Code
#include<bits/stdc++.h>
#define N 2000005
#define re register
using namespace std;
typedef long long ll;
int n,m,q,a[N],pre[N],type;
int size[N],dfn[N],c;
const ll mod = 4294967296;
template<class T>
void read(T &x)
{
char c;int sign=1;
while((c=getchar())>'9'||c<'0') if(c=='-') sign=-1; x=c-48;
while((c=getchar())>='0'&&c<='9') x=(x<<1)+(x<<3)+c-48; x*=sign;
}
struct Edge
{
int next,to;
}edge[N];int head[N],cnt=1;
void add_edge(int from,int to)
{
edge[++cnt].next=head[from];
edge[cnt].to=to;
head[from]=cnt;
}
ll A,B,C,P;
inline int rnd() { return A=(A*B+C)%P; }
void dfs(int rt)
{
dfn[rt]=++c;
size[rt]=1;
for(int i=head[rt];i;i=edge[i].next)
{
int v=edge[i].to;
dfs(v);
size[rt]+=size[v];
}
}
void init()
{
for(re int i=1;i<=n;++i)
{
pre[i]=pre[i-1];
if(a[i]) pre[i]=i;
}
for(re int i=1;i<=n;++i)
{
if(!a[i]) { add_edge(pre[i],i); continue; }
int x=i-m-1;
if(x>0) add_edge(pre[x],i);
else add_edge(0,i);
}
dfs(0);
}
inline bool query(int x,int y)
{
if(!a[y]) y=pre[y];
return dfn[x]<=dfn[y]&&dfn[y]<=dfn[x]+size[x]-1;
}
int main()
{
read(n);read(m);read(q);read(type);
for(re int i=1;i<=n;++i) read(a[i]),a[i]%=2;
init();
ll ans=0;
if(type)
{
read(A);read(B);read(C);read(P);
for(re ll i=1;i<=q;++i)
{
int l=rnd()%n+1,r=rnd()%n+1;
if(l>r) swap(l,r);
if(!m) ans=(ans+i*i*a[l]%mod)%mod;
else if(!query(l,r)) ans=(ans+i*i%mod)%mod;
}
}
else
{
for(re ll i=1;i<=q;++i)
{
int l,r;
read(l);read(r);
if(!m) ans=(ans+i*i*a[l]%mod)%mod;
else if(!query(l,r)) ans=(ans+i*i%mod)%mod;
}
}
cout<<(ans%mod+mod)%mod<<endl;
return 0;
}