Problem H. Cups and Beans 2017.8.11

原题:

There are N cups numbered 0 through N − 1. For each i(1 ≤ i ≤ N − 1), the cup i contains Ai beans,
and this cup is labeled with an integer Ci.
Two people will play the following game:
• In each turn, the player chooses a bean from one of the cups except for the cup 0.
• If he chooses a bean from the cup i, he must move it to one of the cups i − Ci;…… ; i − 1.
• The players take turns alternately. If a player can’t choose a bean, he loses.
Who will win if both players play optimally?

Input:
Input Format:
N
C(1)   A(1)
C(2)   A(2)

C(N−1)   A(N−1)
Constraints:
• 2 ≤ N ≤ 105
• 1 ≤ Ci ≤ i
• 0 ≤ Ai ≤ 109
• At least one of Ai is nonzero.
• All values in the input are integers.

Output:
Print the name of the winner: \First” or \Second”.

Examples:

standard input standard output
3
1 0
1 1
Second
7
1 1
2 0
1 0
2 0
4 1
3 0
First
7
1 1
2 0
1 9
2 10
4 3
3 5
Second

Note:
Notes to the Sample 1:
• In the first turn, the first player must move a bean from 2 to 1.
• In the second turn, the second player must move a bean from 1 to 0.
• In the third turn, the first player can’t choose a bean and loses.

题目大意:

典型的博弈论,N个瓶子,第一个瓶子里没有石子,后面N-1个瓶子里分别有A[i]个石子,每个瓶子上贴了标签C[i],表示每次操作仅可以将这个瓶子里的一个石子石子最多可以移动到前面C[i]个瓶子里(也就是只可以将该瓶子里的一个石子放到 i-C[i] 到 i-1 号瓶子里),最后不能进行移动的人输,求谁赢。

解法分析:

可以将这个问题转化成限定条件的Nim取石子问题,题目的操作是将高位瓶子的石子移动到低位瓶子里,那么石子所在的瓶子标号其实就可以认为是石子堆的石子数,对于每个特定数量的石子堆 i,都有一个限定条件 C[i] 表示最多取i个,A[i] 则表示石子数为i的石子堆有A[i]个。

知道了题意,就可以直接暴力了,枚举前面的 i-C[i] 到 i – 1 的状态然后递推。可是数据范围是1e5,这样做无疑会超时,在周大爷的敏锐观察下,套用了一个主席树维护mex数的模板,就过了。

代码:

#include <bits/stdc++.h>

#define MAXN 100005
using namespace std;
typedef long long LL; #define lc(x) t[x].l
#define rc(x) t[x].r
const int N = 2e5 + , MX = 1e9 + ; struct node {
int l, r, mn;
} t[N * ];
int sz, root[N]; void ins(int &x, int l, int r, int p, int v) {//right of p is v
t[++sz] = t[x];
x = sz;
if (l == r) t[x].mn = v;
else {
int mid = (l + r) >> ;
if (p <= mid) ins(t[x].l, l, mid, p, v);
else ins(t[x].r, mid + , r, p, v);
t[x].mn = min(t[lc(x)].mn, t[rc(x)].mn);
}
} int query(int x, int l, int r, int v) {
if (l == r) return l;
else {
int mid = (l + r) >> ;
if (t[lc(x)].mn < v) return query(t[x].l, l, mid, v);
else return query(t[x].r, mid + , r, v);
}
} int SG[], n;
bool vis[];
int C[], A[]; int main() {
int i, j, k;
scanf("%d", &n);
for (i = ; i < n; i++) {
scanf("%d%d", &C[i + ], &A[i + ]);
}
SG[] = ;
ins(root[],,MX,SG[],);//ins是插入操作,root[1]表示当前树,0表示最小值,MX表示最大值,SG[0]是值,1是位置
for (i = ; i <= n; i++) {
int l = max(i - C[i], ), r = i - ;
SG[i] = query(root[r], , MX, l);
root[i] = root[i-];
ins(root[i],,MX,SG[i],i);
}
// for(int i = 1;i <= n;i++) printf("%d ",SG[i]);
int ans = ;
for (i = ; i <= n; i++) {
if (A[i] % == ) ans ^= SG[i];
}
if (ans) printf("First\n");
else printf("Second\n");
return ;
}

【主席树维护mex】 【SG函数递推】 Problem H. Cups and Beans 2017.8.11的更多相关文章

  1. 牛课练习赛34 Flittle w and Discretization 主席树维护Mex

    ittle w and Discretization 主席树维护Mex. 每个右端点 r 维护出一棵 在[1, r ] 区间中 其他所有的 值离这个 r 最近的的位置是多少. 然后询问区间[L,R]的 ...

  2. 【博弈论】【SG函数】【线段树】Petrozavodsk Summer Training Camp 2016 Day 9: AtCoder Japanese Problems Selection, Thursday, September 1, 2016 Problem H. Cups and Beans

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

  3. 一类SG函数递推性质的深入分析——2018ACM陕西邀请赛H题

    题目描述 定义一种有根二叉树\(T(n)\)如下: (1)\(T(1)\)是一条长度为\(p\)的链: (2)\(T(2)\)是一条长度为\(q\)的链: (3)\(T(i)\)是一棵二叉树,它的左子 ...

  4. UVa 10561 (SG函数 递推) Treblecross

    如果已经有三个相邻的X,则先手已经输了. 如果有两个相邻的X或者两个X相隔一个.,那么先手一定胜. 除去上面两种情况,每个X周围两个格子不能再放X了,因为放完之后,对手下一轮再放一个就输了. 最后当“ ...

  5. Light OJ 1296 - Again Stone Game (博弈sg函数递推)

    F - Again Stone Game Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu ...

  6. CodeForces 464E The Classic Problem | 呆克斯歘 主席树维护高精度

    题意描述 有一个\(n\)点\(m\)边的无向图,第\(i\)条边的边权是\(2^{a_i}\).求点\(s\)到点\(t\)的最短路长度(对\(10^9 + 7\)取模). 题解 思路很简单--用主 ...

  7. 【10.10校内测试】【线段树维护第k小+删除】【lca+主席树维护前驱后驱】

    贪心思想.将a排序后,对于每一个a,找到对应的删除m个后最小的b,每次更新答案即可. 如何删除才是合法并且最优的?首先,对于排了序的a,第$i$个那么之前就应该删除前$i-1$个a对应的b.剩下$m- ...

  8. 【洛谷5294】[HNOI2019] 序列(主席树维护单调栈+二分)

    点此看题面 大致题意: 给你一个长度为\(n\)的序列\(A\),每次询问修改一个元素(只对当前询问有效),然后让你找到一个不下降序列\(B\),使得这两个序列相应位置之差的平方和最小,并输出这个最小 ...

  9. POJ_3090 Visible Lattice Points 【欧拉函数 + 递推】

    一.题目 A lattice point (x, y) in the first quadrant (x and y are integers greater than or equal to 0), ...

随机推荐

  1. 通用输入输出端口 - GPIO

    一.概述 GPlO ( General Purpose I/0 Ports )意思为通用输入/输出端口, 通俗地说, 就是一些引脚.在芯片手册中I/O端口一般是分组的,比如有的芯片分为 A-J 共 9 ...

  2. OC之block 和协议

    一.BOLCK (一)简介 BLOCK是什么?苹果推荐的类型,效率高,在运行中保存代码.用来封装和保存代码,有点像函数,BLOCK可以在任何时候执行. BOLCK和函数的相似性:(1)可以保存代码(2 ...

  3. Wireshark工具抓包的数据包分析

    Wireshark(前称Ethereal)是一个网络封包分析软件.网络封包分析软件的功能是撷取网络封包,并尽可能显示出最为详细的网络封包资料. Wireshark使用WinPCAP作为接口,直接与网卡 ...

  4. DataSet和泛型之间相互转换

    取数据的时候,存储过程返回了多个结果集,后台用DataSet去接收这几个结果集,然后接收之后,需要将结果集转换为不同的实体,于是下面的代码便出现了. /// <summary> /// 将 ...

  5. 如何给ioloop.run_sync()中调用的函数传入参数

    问题 如何给tornado.ioloop.IOLoop中的run_sync方法中调用的函数添加参数 解决方案 使用functools.partial 解决示例 from tornado import ...

  6. 【JavaWeb】从零实现用户登录

    1.数据库预备 1.1 SQL 创建数据库 create database db; 创建表 create table userInfo( id int primary key , name ), pa ...

  7. 使用NPOI将数据导出Excel

    NPOI.HSSF.UserModel.HSSFWorkbook book = new NPOI.HSSF.UserModel.HSSFWorkbook(); NPOI.SS.UserModel.IS ...

  8. Leecode刷题之旅-C语言/python-141环形链表

    /* * @lc app=leetcode.cn id=141 lang=c * * [141] 环形链表 * * https://leetcode-cn.com/problems/linked-li ...

  9. 利用谷歌翻译网站和Adobe Acrobat翻译英文文档,且鼠标放置后显示英文原文(无字数限制)(18/12/11更新)

    软件:Adobe Acrobat 网页:https://translate.google.cn/?tr=f&hl=zh-CN 方法:       第一步:用Adobe Acrobat 打开英文 ...

  10. js polyfill , to developing the cross browser js

    https://github.com/paulmillr/console-polyfill https://github.com/Modernizr/Modernizr/wiki/HTML5-Cros ...