zoukankan      html  css  js  c++  java
  • [bzoj3729]Gty的游戏

    来自FallDream的博客,未经允许,请勿转载,谢谢。


    某一天gty在与他的妹子玩游戏。
    妹子提出一个游戏,给定一棵有根树,每个节点有一些石子,每次可以将不多于L的石子移动到父节点,询问
    将某个节点的子树中的石子移动到这个节点先手是否有必胜策略。
    gty很快计算出了策略。
    但gty的妹子十分机智,她决定修改某个节点的石子或加入某个新节点。
    gty不忍心打击妹子,所以他将这个问题交给了你。
    另外由于gty十分绅士,所以他将先手让给了妹子。

    n,m<=5*10^4

    首先和询问节点同奇偶的肯定不用考虑,然后不同奇偶的每个点手推一下发现nim值是w%(L+1)

    然后只要维护奇偶深度的区间异或和即可,考虑以dfs序为下标建splay。

    插入一个点可以直接插入到父亲后面,询问的时候从根向右找到最远的深度大于根的深度的一段即可。

    复杂度nlogn

    #include<iostream>
    #include<cstdio>
    #define MN 100000
    using namespace std;
    inline int read()
    {
        int x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    
    bool b[MN+5];
    int n,L,m,head[MN+5],cnt=0,size[MN+5],in[MN+5],dep[MN+5],rt,last=0,mn[MN+5];
    int fa[MN+5],c[MN+5][2],s1[MN+5],s2[MN+5],w[MN+5],q[MN+5],top=0;
    struct edge{int to,next;}e[MN+5];
    inline void ins(int f,int t){e[++cnt]=(edge){t,head[f]};head[f]=cnt;}
    
    void Dfs(int x)
    {
        q[++top]=x;
        for(int i=head[x];i;i=e[i].next)
            dep[e[i].to]=dep[x]+1,Dfs(e[i].to);
    }
    
    void update(int x)
    {
        int l=c[x][0],r=c[x][1];
        size[x]=size[l]+size[r]+1;
        if(dep[x]&1) s1[x]=w[x],s2[x]=0;
        else s1[x]=0,s2[x]=w[x];
        s1[x]^=s1[l]^s1[r];s2[x]^=s2[l]^s2[r];
        mn[x]=dep[x];
        if(l) mn[x]=min(mn[x],mn[l]);
        if(r) mn[x]=min(mn[x],mn[r]);
    }
    
    void rotate(int x,int&k)
    {
        int y=fa[x],z=fa[y],l=c[y][1]==x,r=l^1;
        if(y==k) k=x; else c[z][c[z][1]==y]=x;
        fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
        c[y][l]=c[x][r];c[x][r]=y;
        update(y);update(x);
    }
    
    void splay(int x,int&k)
    {
        for(;x!=k;rotate(x,k))
            if(fa[x]!=k) rotate((c[fa[fa[x]]][1]==fa[x]^c[fa[x]][1]==x)?x:fa[x],k);
    }
    
    void build(int&x,int l,int r,int last)
    {
        if(l>r){last=0;return;}
        int mid=l+r>>1;x=q[mid];fa[x]=last;
        build(c[x][0],l,mid-1,x);
        build(c[x][1],mid+1,r,x);
        update(x);
    }
    
    int GetRank(int x)
    {
        int sum=1+size[c[x][0]];
        for(int y;x!=rt;x=y)
        {
            y=fa[x];
            if(c[y][1]==x) sum+=size[c[y][0]]+1;
        }
        return sum;
    }
    
    void ins(int&x,int rk,int y,int last)
    {
        if(!x){x=y;fa[x]=last;update(x);return;}
        int Sz=size[c[x][0]]+1;
        if(Sz<=rk) ins(c[x][1],rk-Sz,y,x);
        else ins(c[x][0],rk,y,x);
        update(x);
    }
    
    int Find(int x,int D)
    {
        if(!x) return 0;
        if(min(dep[x],mn[c[x][0]])>D)
            return Find(c[x][1],D);
        else if(mn[c[x][0]]>D) return x;
        else return Find(c[x][0],D);
    }
    
    int main()
    {
        n=read();L=read();mn[0]=23333333;
        for(int i=1;i<=n;++i) w[i]=read()%(L+1);
        for(int i=1;i<n;++i)
        {
            int f=read(),t=read();
            ++in[t];ins(f,t);
        }
        q[++top]=MN+1;Dfs(1);q[++top]=MN+2;
        build(rt,1,top,0);m=read();
        for(int i=1;i<=m;++i)
        {
            int op=read();
            if(op==1)
            {
                int x=read()^last;
                splay(x,rt);int Rt=Find(c[rt][1],dep[x]);
                splay(Rt,c[rt][1]);int z=c[c[rt][1]][0],res=dep[x]&1?s2[z]:s1[z];
                if(!z||res==0) puts("GTY");
                else puts("MeiZ"),++last;
            }
            if(op==2)
            {
                int x=read()^last,y=read()^last;
                w[x]=y%(L+1);for(int i=x;i;i=fa[i]) update(i);
            }
            if(op==3)
            {
                int x=read()^last,y=read()^last,Rk=GetRank(x);
                w[y]=(read()^last)%(L+1);dep[y]=dep[x]+1;
                ins(rt,Rk,y,0);
            }
        }
        return 0;
    }
  • 相关阅读:
    Shiro 学习笔记(Realm)
    Shiro 学习笔记(Authentication)
    Shiro 学习笔记(基本结构)
    POI 示例(导入,导出)
    SpringBoot 整合POI
    解决使用drf-haystack报错ImportError: cannot import name get_count
    python实现冒泡排序和插入排序
    九大排序算法总结(转)
    Djaong 数据库查询
    django session 和cookie的设置,获取和删除
  • 原文地址:https://www.cnblogs.com/FallDream/p/bzoj3729.html
Copyright © 2011-2022 走看看