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到点连边

    这个转化挺巧妙的。。

    自己果然还是菜

  • 相关阅读:
    城市的划入划出效果
    文本溢出省略解决笔记css
    长串英文数字强制折行解决办法css
    Poj 2352 Star
    树状数组(Binary Indexed Trees,二分索引树)
    二叉树的层次遍历
    Uva 107 The Cat in the Hat
    Uva 10336 Rank the Languages
    Uva 536 Tree Recovery
    Uva10701 Pre, in and post
  • 原文地址:https://www.cnblogs.com/supy/p/6905356.html
Copyright © 2011-2022 走看看