Codeforces 1458E - Nim Shortcuts(博弈论+BIT)
首先看到这样的题我们不妨从最特殊的情况入手,再逐渐推广到一般的情况。考虑如果没有特殊点的情况,我们将每个可能的局面看作一个点 \((a,b)\) 并映射到坐标系上。考虑按照博弈论的套路求出每个点是必胜点还是必输点,就这题而言,显然一个点 \((x,y)\) 是必胜点当且仅当 \(\exists z<x\) 满足 \((z,y)\) 是必胜点或者 \(\exists z<y\) 满足 \((y,z)\) 是必胜点。打个表 即可知道一个状态 \((x,y)\) 为 P 态(必输点)当且仅当 \(x=y\),否则该状态为 N 态(必胜点)。这个异常好理解,如果 \(x=y\) 那不论先手取了多少石子,后手都可以在另一堆中取相同数量的棋子,最终肯定会留给先手一个 \((0,0)\) 的局面。
紧接着我们考虑有一个特殊点的情况,我们假设这个特殊点为 \((x,y)\),那么可以分出三种情况:
\(x=y\),那么这个点本来就是 P 态,显然不会对每个点的 N/P 态产生任何影响
\(x>y\),如图所示,假设该点为 \(P\),那么该点在直线 \(y=x\) 的右下方。显然该点不会对该点左边及下方的点的状态产生影响,也就是说产生直接影响的只可能是 \(P\) 沿 \(+x\) 方向引出的射线(图中的黄色射线)或沿 \(+y\) 方向引出的射线(图中的橙色射线),将这些点全都变成 N 态。而显然黄色射线上的所有点本来就是 N 态,橙色射线上的点除了其与 \(y=x\) 的交点其他也都是 N 态,故这个点产生的效果是将橙色射线与 \(y=x\) 的交点 \((x,x)\) 变为 N 态,但这样会带来一个副作用,那就是 \((x,x)\) 变为 N 态了,\((x+1,x)\) 反而无法直接到达 N 态的点,变成 P 态了,按照类似的方式归纳也可知道这样会导致 \((x+2,x+1),(x+3,x+2),\cdots,(k+1,k)\) 变为 P 态,即图中的红色部分为 P 态,其余为 N 态。

\(x<y\),与 \(x<y\) 的情况类似,只不过变成 \((y,y)\) 变为 N 态,\((y,y+1),(y+1,y+2),\cdots\) 变为 P 态。
\(n\le 1\) 的情况已经解决了,那么怎样解决原题呢?
注意到题目有个显然的性质就是每行每列中除特殊点外最多一个 P 点,也就是说每列除特殊点外的 P 点组成的函数是一个分段函数,并且每段都是一个形如 \(y=x+k\) 的函数,比方说下图:

我们考虑重新观察一下上面每个关键点的作用效果。对于每个向上引出射线的关键点(例如图中的 \(P_1\)),我们可以近似地看作删除了该关键点所在的列并将左右两部分重新拼在一起,对于每个向右引出射线的关键点我们也可近似地看作删除了该关键点所在的行,这样一来思路就来了,我们将所有关键点按横坐标从小到大排序,对于一个关键点 \((x,y)\),我们记 \(s\) 为 \(x\) 前面有多少列被删除,\(t\) 为 \(y\) 前面有多少行被删除,那么该关键点所在部分 P 态的点的函数表达式就是 \(y=x+s-t\),我们按照线性规划的思想将这个点与这条线的关系进行比较,如果 \(y<x+s-t\) 那么该点应当向上引出射线,即删除这一列,那么我们只需令 \(s\) 加一,注意如果这一列已经删除了就不用再删了。如果 \(y=x+s-t\) 那么该点可以直接忽略,如果 \(y>x+s-t\) 那么应当删除这一行。最后考虑回答每个询问,首先特判掉待询问点与某个关键点重合的情况,此时答案显然为 LOSE,其次如果存在某个关键点与待询问点同行同列,那么答案显然是 WIN,否则我们还是求出 \(s\) 表示 \(x\) 前面有多少列被删除,\(t\) 表示 \(y\) 前面有多少行被删除,并检验 \((x,y)\) 是否在 \(y=x+s-t\) 上即可。求 \(t\) 可以采用离散化+树状数组。
时间复杂度 \(n\log n\)。
const int MAXN=1e5;
int n,m;
struct event{
int x,y,id;
bool operator <(const event &rhs) const{
if(x!=rhs.x) return x<rhs.x;
else if(y!=rhs.y) return y<rhs.y;
return id<rhs.id;
}
} a[MAXN*2+5];
int key[MAXN*2+5],uni[MAXN*2+5],cnt=0,num=0;
int get(int x){return lower_bound(uni+1,uni+num+1,x)-uni;}
bool is[MAXN*2+5],ans[MAXN+5];int c1=0,lst=0;
int t[MAXN*2+5];
void add(int x){for(int i=x;i<=num;i+=(i&-i)) t[i]++;};
int query(int x){int ret=0;for(int i=x;i;i&=(i-1)) ret+=t[i];return ret;}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d%d",&a[i].x,&a[i].y),key[++cnt]=a[i].y;
for(int i=1;i<=m;i++) scanf("%d%d",&a[i+n].x,&a[i+n].y),a[i+n].id=i,key[++cnt]=a[i+n].y;
sort(a+1,a+n+m+1);sort(key+1,key+cnt+1);key[0]=-1;
for(int i=1;i<=cnt;i++) if(key[i]!=key[i-1]) uni[++num]=key[i];
for(int i=1;i<=n+m;i++){
int pos=get(a[i].y);
if(a[i].id){
if(a[i-1].x==a[i].x&&a[i-1].y==a[i].y) ans[a[i].id]=1;
else if(a[i].x!=lst&&!is[pos]){
int dif=query(pos)-c1;
// printf("%d\n",dif);
if(a[i].y==a[i].x+dif) ans[a[i].id]=1;
}
} else {
int dif=query(pos)-c1;
if(a[i].x+dif<a[i].y){//up
if(!is[pos]) add(pos),is[pos]=1;
} else if(a[i].x+dif>a[i].y){//down
if(lst!=a[i].x) lst=a[i].x,c1++;
}
}
}
for(int i=1;i<=m;i++) printf("%s\n",(ans[i])?"LOSE":"WIN");
return 0;
}
Codeforces 1458E - Nim Shortcuts(博弈论+BIT)的更多相关文章
- 【HDU3032】Nim or not Nim?(博弈论)
[HDU3032]Nim or not Nim?(博弈论) 题面 HDU 题解 \(Multi-SG\)模板题 #include<iostream> #include<cstdio& ...
- CodeForces - 1162E Thanos Nim (博弈论)
Alice and Bob are playing a game with nn piles of stones. It is guaranteed that nn is an even number ...
- BZOJ3105: [cqoi2013]新Nim游戏 博弈论+线性基
一个原来写的题. 既然最后是nim游戏,且玩家是先手,则希望第二回合结束后是一个异或和不为0的局面,这样才能必胜. 所以思考一下我们要在第一回合留下线性基 然后就是求线性基,因为要取走的最少,所以排一 ...
- POJ2975 Nim 【博弈论】
DescriptionNim is a 2-player game featuring several piles of stones. Players alternate turns, and on ...
- HDU.3032.Nim or not Nim?(博弈论 Lasker's Nim)
题目链接 \(Description\) 有多堆石子, 每次可以将任意一堆拿走任意个或者将这一堆分成非空的两堆, 拿走最后一颗石子的人胜利.问谁会获得胜利. \(Solution\) Lasker's ...
- 2018.09.25 poj2068 Nim(博弈论+dp)
传送门 题意简述:m个石子,有两个队每队n个人循环取,每个人每次取石子有数量限制,取最后一块的输,问先手能否获胜. 博弈论+dp. 我们令f[i][j]f[i][j]f[i][j]表示当前第i个人取石 ...
- POJ 2975 Nim(博弈论)
[题目链接] http://poj.org/problem?id=2975 [题目大意] 问在传统的nim游戏中先手必胜策略的数量 [题解] 设sg=a1^a1^a3^a4^………^an,当sg为0时 ...
- Codeforces 786A Berzerk(博弈论)
[题目链接] http://codeforces.com/problemset/problem/786/A [题目大意] 有两个人,每个人有一个数集,里面有一些数,现在有一个环,有个棋子放在1, 有个 ...
- Leetcode 292 Nim Game 博弈论
class Solution {public: bool canWinNim(int n) { return n % 4 != 0; }};
随机推荐
- Hive面试题整理(一)
1.Hive表关联查询,如何解决数据倾斜的问题?(☆☆☆☆☆) 1)倾斜原因:map输出数据按key Hash的分配到reduce中,由于key分布不均匀.业务数据本身的特.建表时考虑不周.等原因 ...
- Bubble和BubbleButton气泡框
from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.lang.builder import Buil ...
- [CSP-S 2021] 回文
题目描述: 给定正整数 n 和整数序列 a1, a2,-,a2n,在这 2n 个数中,1, 2,-,n 分别各出现恰好 2 次.现在进行 2n 次操作,目标是创建一个长度同样为 2n 的序列 b 1, ...
- STM32中断编程三步曲教你弄会中断设置以及中断优先级设置
中断作为stm32中必不可少的一个功能,其重要性是不言而喻的因此把中断学习好是根本. 所以今天就来好好啃一下中断配置的知识,俗话说:磨刀不误砍柴工.问题是什么呢?项目中我用到了一个触摸键盘TTP229 ...
- 洛谷 P6075 [JSOI2015]子集选取
链接:P6075 前言: 虽然其他大佬们的走分界线的方法比我巧妙多了,但还是提供一种思路. 题意: %&¥--@#直接看题面理解罢. 分析过程: 看到这样的题面我脑里第一反应就是DP,但是看到 ...
- ArrayList集合底层原理
目录 ArrayList集合特点及源码分析 ArrayList源码分析 成员变量 构造函数 增加方法 add(E e)方法 add(int index, E element)方法 删除方法 remov ...
- 基于openeuler的openssl编程
------------恢复内容开始------------ 一.编译环境 我下载好之后默认安装了openssl,若未安装的可输入以下命令: wget https://www.openssl.org/ ...
- 设计模式(1-3)-动态代理(WeakCache的运用)
阅读本篇文章前,请事先阅读 理解Java的强引用.软引用.弱引用和虚引用. 看看什么是强引用.什么是弱引用及它们的用途,很必要!!! 上一节讲到,获取对应的代理类时,首先会从缓存中去拿,若拿不到才会去 ...
- java实现rsa加密算法【5min快速应用教程】
该篇文章的主要目的是让读者能够迅速应用到项目中,想要了解详细的rsa加密算法的,可以百度找到更多原理.深度分析的文章. RSA算法是一种非对称密码算法,所谓非对称,就是指该算法需要一对密钥,使用其中一 ...
- 【网络好文】---MySQL为Null导致的四大坑
正式开始之前,我们先来看下 MySQL 服务器的配置和版本号信息,如所示: select version(); -- 版本为 8.0.22 "兵马未动粮草先行",看完了相关的配置之 ...