[] LGOJ5652 basis of game theory exercises

Do you think this is a road game theory problem, in fact, it is indeed ah ......

The examination room full of ideas on what to say

First consider backwards, if the number of the last frame is odd, what happens?

To sample an example

Obviously, if we come to the last frame, you can only jump on top of the cross repeatedly, until the complete disappearance of this column grid

It is easy to find such a case, the last one is a winning point (here defined as the first point win must come here to win)

So, in the front row of the m columns, the columns are all doomed to failure point (because if come here, come next opponents will be able to win points)

Point win represented in red, blue represents the point of losing

Then continue to consider, if you want to go to avoid the blue column (losing points), the last two will cross again jump on the second row until the row disappears

Sound familiar? Correct! This is the beginning of the case and the same!

But here, the last frame is even, apparently it is doomed to failure point (the upper hand in the past will lose)

That is what the row in front of it the point of it? Because it is an even number, so inherited the previous case, the point is doomed to failure

Here, we can already draw a conclusion on:

倒推,如果最后一列是奇数,那么这一列是必胜点,它前面的m列都必败
如果最后一列是偶数,那么这一列是必败点,所有玩家都会尽量避免走到这一列来

So we can not even consider the side! Order of enumeration, for each column, put 它前面的第一个必胜点him even side

In this case, even after a good map is a zero-rooted multi-branch tree!

For each inquiry l and r, if r l is the ancestor, then the upper hand to win, otherwise FLAC win!

So now the question is, given a fixed form of a tree, how \ (\ Theta (1) \ ) to determine whether u v ancestors is it?

dfs order!

Statistic timestamp a point for the first time be accessed in the course of the dfs, as dfn

If \ (dfn [u] \ leq dfn [v] \ leq dfn [u] + size [u] -1 \) , then, u is v ancestors!

Then this problem will solved it!

Specifically looking at the code it

#include<bits/stdc++.h>
#define mod (1LL<<32)
#define ll long long
#define int long long
#define N 20000005
using namespace std;

int n,m,q,type,l[N],r[N];
int L,a[N],fa[N];//fa->这个点前面的第一个必胜转移点 
ll ans=0;

int A,B,C,P;
inline int rnd(){return A=(A*B+C)%P;}

struct Edge
{
    int next,to;
}edge[N];
int cnt=0,head[N];

inline void add_edge(int from,int to)
{
    edge[++cnt].next=head[from];
    edge[cnt].to=to;
    head[from]=cnt;
}

template<class T>inline void read(T &res)
{
    char c;T flag=1;
    while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
    while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
}

int siz[N],dfn[N],tms;
void dfs(int u,int fa)
{
//  cout<<"dfs: "<<u<<" "<<fa<<endl;
    siz[u]=1;
    if(!dfn[u]) dfn[u]=++tms;
    for(register int i=head[u];i;i=edge[i].next)
    {
        int v=edge[i].to;
        if(v==fa) continue;
        dfs(v,u);
        siz[u]+=siz[v];
    }
}

signed main()
{
    read(n);read(m);read(q);read(type);//数的个数,区间长度,询问,是否压缩 
    for(register int i=1;i<=n;++i) read(a[i]);
    if(!type)
    {
        for(register int i=1;i<=q;++i)
            read(l[i]),read(r[i]);
    }
    else
    {
        read(A);read(B);read(C);read(P);
        for(register int i=1;i<=q;++i)
        {
            l[i]=rnd()%n+1;
            r[i]=rnd()%n+1;
            if(l[i]>r[i]) swap(l[i],r[i]);
        }
    }
    
    for(register int i=1;i<=n;++i)
    {
        L=max(0LL,i-m-1);
        if(a[i]&1)//奇数是必胜点
        {
            if(a[L]&1) fa[i]=L,add_edge(L,i);
            else fa[i]=fa[L],add_edge(fa[L],i);
        }
        else//偶数,先手必败 
        {
            if(a[i-1]&1) fa[i]=i-1,add_edge(i-1,i);
            else fa[i]=fa[i-1],add_edge(fa[i-1],i);
        }
    }
    //处理出每个点倒序第一个必胜转移点 

    dfs(0,0);//dfs序 
//  for(register int i=1;i<=n;++i) cout<<siz[i]<<endl;
    for(register int i=1;i<=q;++i)
    {
        int u=l[i],v=r[i];
        if(u==v)
        {
            if(a[u]&1) continue;
            else ans=(ans+i*i)%mod;
            continue;
        }
//      cout<<dfn[u]<<" "<<dfn[v]<<" "<<dfn[u]+siz[u]-1<<endl;
        if(dfn[u]<=dfn[v]&&dfn[v]<=dfn[u]+siz[u]-1) continue;//先手必胜,没有贡献 
        ans=(ans+i*i)%mod;
    }
    printf("%lld\n",ans);
    return 0;
}

/*
4 2 1 0
2 2 0 0
1 4
*/

Guess you like

Origin www.cnblogs.com/tqr06/p/11854590.html