zoukankan      html  css  js  c++  java
  • 【博弈论】【SG函数】【线段树】Petrozavodsk Summer Training Camp 2016 Day 9: AtCoder Japanese Problems Selection, Thursday, September 1, 2016 Problem H. Cups and Beans

    一开始有n个杯子,每个杯子里有一些豆子,两个人轮流操作,每次只能将一个豆子移动到其所在杯子之前的某个杯子里,不过可以移动到的范围只有一段区间。问你是否先手必胜。

    一个杯子里的豆子全都等价的,因为sg函数是异或起来的值,所以一个杯子里如果有偶数个豆子,就没有意义。

    用sg(i)表示i杯子中的豆子的sg值,sg(i)就是其所能移动到的那段杯子的区间的sg值的mex(未出现的最小非负整数)。可以用线段树去做。是经典问题。

    由于每次看似是后缀询问,实则是全局询问,故而主席树完全是多余的。

    回顾一下区间mex的求法:

    主席树里每个值的位置存当前该值出现的最右位置。

    如果root[r]的前缀主席树中,某值最右位置大于等于l,说明该值出现在了l,r中。

    所以主席树维护区间最小值,如果左半值域的最小值<l,则说明左半值域有值未在l,r出现,则查询左子树;否则查询右子树。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define N 100010
    struct Node{int v,lc,rc;}T[N*22];
    int root[N],e;
    void Insert(int pre,int cur,int p,int v,int l,int r)
    {
        if(l==r)
          {
            T[cur].v=v;
            return;
          }
        int m=(l+r>>1);
        if(p<=m)
          {
            T[cur].lc=++e;
            T[cur].rc=T[pre].rc;
            Insert(T[pre].lc,T[cur].lc,p,v,l,m);
          }
        else
          {
            T[cur].rc=++e;
            T[cur].lc=T[pre].lc;
            Insert(T[pre].rc,T[cur].rc,p,v,m+1,r);
          }
        T[cur].v=min(T[T[cur].lc].v,T[T[cur].rc].v);
    }
    int Goal;
    int Query(int R,int l,int r)
    {
        if(l==r) return l;
        int m=(l+r>>1);
        if(T[T[R].lc].v<Goal) return Query(T[R].lc,l,m);
        else return Query(T[R].rc,m+1,r);
    }
    int n,a[N],C[N],anss[N];
    int main()
    {
    //	freopen("h.in","r",stdin);
        int x,y;
        scanf("%d",&n);
        root[1]=++e;
        Insert(root[0],root[1],1,1,1,100001);
        for(int i=1;i<n;++i)
          {
            scanf("%d%d",&C[i],&a[i]);
            Goal=i+1-C[i];
            anss[i]=Query(root[i],1,100001)-1;
            root[i+1]=++e;
            Insert(root[i],root[i+1],anss[i]+1,i+1,1,100001);
          }
        int ans=0;
        for(int i=1;i<n;++i){
        	if(a[i]&1){
        		ans^=anss[i];
        	}
        }
        puts(ans ? "First" : "Second");
        return 0;
    }
  • 相关阅读:
    Linux下的lds链接脚本简介(一)
    linux字符驱动之poll机制按键驱动
    Linux中断处理驱动程序编写
    基于Hexo + Git + Nginx的博客发布
    Visual Studio2012打开时弹出“遇到异常:这可能是由某个扩展导致的”错误的解决办法
    卫星轨道和两行数据TLE
    C#基础系列:开发自己的窗体设计器(PropertyGrid显示中文属性名)
    C# WinForm PropertyGrid用法
    C#基础系列:实现自己的ORM(反射以及Attribute在ORM中的应用)
    [转]计算机视觉、机器学习相关领域论文和源代码大集合
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/7376692.html
Copyright © 2011-2022 走看看