zoukankan      html  css  js  c++  java
  • Codeforces Round #406 (Div. 2)滚粗记

    A 一看到题,不是一道解不定方程的裸题吗,调了好久exgcd。 其实一个for就好了啊

    B 一直WA ON TEST 7真是烦,一想会不会是编号太大了,又写了一个map版本,无用。

    调了好久好久才发现有几次询问没有读完mmp

    C 调了一晚上,又看了数篇题解,终于看懂了QAQ

    这是一道博弈论,借助图论/DP帮助完成。

    博弈中有3种状态:必胜,必败,不一定

    而我们需要将这些状态一直转移以求得结果。

    如果A无论怎么移动,使B下一步必胜,则A的现在状态为必败。
    如果A可以移动任意一步,使B下一步必败,则A现在的状态为必胜。

    没被搜到就不一定。

    大致思路就是这样,考虑具体实现。

    1.如果从每个状态正着搜,显然不行。只能由终止状态倒着推

    2.每个状态记录一下入度,且每次若转移需要判重! 经计算,queue空间为4*n

    3.思路要清晰,要清楚我们输出的是什么东西(我昨晚一直思路混乱,多求了很多没用的东西)

    4.注意细节,我好粗心好粗心啊

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    #define rep(i,a,b) for (int i=a; i<=b; i++)
    typedef long long ll;
    using namespace std;
    #define N 7005
    int n,k[2],s[2][N],dp[2][N]; //1 win  0 loop  -1 lose
    int Degree[2][N]; //此时先手者 
    struct Node {
        int p,turn;
    } q[N<<2],u,v;
    
    inline void read(int &x) {
        x=0; char c=getchar(); int f=1;
        while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
        while (c>='0'&&c<='9') {x=10*x+c-'0'; c=getchar();} x*=f;
    }
    inline void bfs() {
        int f=0,r=2;
        u.p=1; u.turn=0; q[0]=u; dp[0][1]=-1;
        u.turn=1; q[1]=u; dp[1][1]=-1;
        rep(i,1,n) rep(j,0,1) Degree[j][i]=k[j]; //此时先手者
        while (f!=r) {
            u=q[f++]; int now=u.turn;
            rep(i,1,k[now^1]) { //len!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                int dot=(u.p-s[now^1][i]+n-1)%n+1; //% !!!!!!!!!!
                if (dot==1) continue; //can't be realized!!!!!!!!
                if (dp[now][u.p]==-1) {
                    if (dp[now^1][dot]==1) continue;
                    dp[now^1][dot]=1;
                    v.turn=u.turn^1; v.p=dot;
                    q[r++]=v;
                }
                else if (dp[now][u.p]==1) {
                //    if (dp[now^1][dot]==1) continue;    if win,can't lose!!
                    if ((--Degree[now^1][dot])==0) {
                        dp[now^1][dot]=-1;
                        v.turn=u.turn^1; v.p=dot;
                        q[r++]=v;
                    }
                }
            }
        }
    }
    int main() {
    //    freopen("1.in","r",stdin);
        read(n);
        rep(i,0,1) {read(k[i]); rep(j,1,k[i]) read(s[i][j]);}
        bfs();
        rep(i,0,1) {
            rep(j,2,n)
                if (dp[i][j]==1) printf("Win ");
                else if (dp[i][j]==-1) printf("Lose ");
                else printf("Loop ");
            puts("");
        }
        return 0;
    }

     D 线段树/虚拟点优化建图

    直接建图不可能,这种区间题肯定是裸的线段树

    建两棵线段树,每个节点代表一个区间,对于2、3操作,最多连log条边。

    第1棵:上到下连边 ;第2棵:下到上连边 

    操作2:点到tree1的node连边

    操作3:tree2的node到点连边

    这个转化挺巧妙的。。

    自己果然还是菜

  • 相关阅读:
    2019牛客多校 Round10
    2019牛客多校 Round9
    2019牛客多校 Round8
    2019牛客多校 Round7
    2019HDU多校 Round8
    2019HDU多校 Round7
    elasticsearch分词器
    elasticsearch的mapping
    elasticsearch批量操作
    elasticsearch元数据
  • 原文地址:https://www.cnblogs.com/supy/p/6905356.html
Copyright © 2011-2022 走看看