zoukankan      html  css  js  c++  java
  • [洛谷P5652]基础博弈练习题

    题目

    思路

    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;
    }
    
  • 相关阅读:
    团队项目-选题报告
    图论3-分层图最短路
    图论2-次短路计数
    图论1-k短路
    noi online 提高组t2冒泡排序
    图和树
    搜索(bfs)
    搜索(dfs)
    笔记
    打工
  • 原文地址:https://www.cnblogs.com/Chtholly/p/11852998.html
Copyright © 2011-2022 走看看