CF1236D Alice&Doll

题目描述

有一个机器人在一个\(n\times m\)的有\(k\)个障碍网格上移动,上北下南左西右东。

它一开始在第一行第一列,面朝东边。它在每个格子上可以右转一次或不右转,然后会向面向的方向走一步。

问能不能将所有不是障碍的格子都走恰好一遍。\(n,m,k\leq10^5\)

题解

会发现每个格只能右转一次,所以最后走出的路径大概这样:

-------------------
* |
* |
|----------* |
| *-----| |
*------------------

手动模拟这个过程就行。

注意考虑在一开始就拐弯的情况,不然会FST。

代码

#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#define LL long long
#define rep(i,x,y) for(int i=(x);i<=(y);++i)
#define dwn(i,x,y) for(int i=(x);i>=(y);--i)
#define view(u,k) for(int k=fir[u];~k;k=nxt[k])
#define maxn 100007
using namespace std;
int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)&&ch!='-')ch=getchar();
if(ch=='-')f=-1,ch=getchar();
while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return x*f;
}
void write(int x)
{
char ch[20];int f=0;
if(!x){putchar('0'),putchar('\n');return;}
if(x<0)putchar('-'),x=-x;
while(x)ch[++f]=x%10+'0',x/=10;
while(f)putchar(ch[f--]);
putchar('\n');
}
vector<int>nd[2][maxn];
int p[2][maxn],n,m,k,mx[4],now,f;
bool cmpy(int x,int y){return p[1][x]<p[1][y];}
bool cmpx(int x,int y){return p[0][x]<p[0][y];}
int getp(int rc,int k,int x,int f)
{
if(nd[rc][k].size()==0)return -1;
int l=0,r=nd[rc][k].size()-1,ans=-1;
if(f==0&&p[rc^1][nd[rc][k][l]]>x)return -1;
if(f==1&&p[rc^1][nd[rc][k][r]]<x)return -1;
while(l<=r)
{
int mid=l+r>>1;
if((!f&&p[rc^1][nd[rc][k][mid]]<=x)||(f&&p[rc^1][nd[rc][k][mid]]>=x))
{
if(!f)ans=max(ans,mid),l=mid+1;
else ans=ans==-1?mid:min(ans,mid),r=mid-1;
}
else
{
if(!f)r=mid-1;
else l=mid+1;
}
}
if(ans!=-1)ans=nd[rc][k][ans];
return ans;
}
int main()
{
n=read(),m=read(),k=read();mx[0]=m,mx[1]=n,mx[2]=mx[3]=1;
rep(i,1,k){p[0][i]=read(),p[1][i]=read(),nd[0][p[0][i]].push_back(i),nd[1][p[1][i]].push_back(i);if(p[0][i]==1&&p[1][i]==2)f=1;}
rep(i,1,n)sort(nd[0][i].begin(),nd[0][i].end(),cmpy);
rep(i,1,m)sort(nd[1][i].begin(),nd[1][i].end(),cmpx);
int px=1,py=1;LL sum=(LL)n*m-1;
if(m==1)f=1;
if(f)now=1,mx[0]=1;
while(1)
{
int pre=now-1;if(pre==-1)pre=3;
if(now==0)
{
int x=getp(0,px,py,1);
if(x!=-1)x=min(mx[now],p[1][x]-1);
else x=mx[now];
if(x==py)break;
sum-=(LL)(x-py);
mx[pre]=px+1,py=x;
}
else if(now==1)
{
int x=getp(1,py,px,1);
if(x!=-1)x=min(mx[now],p[0][x]-1);
else x=mx[now];
if(x==px)break;
sum-=(LL)(x-px);
mx[pre]=py-1,px=x;
}
else if(now==2)
{
int x=getp(0,px,py,0);
if(x!=-1)x=max(mx[now],p[1][x]+1);
else x=mx[now];
if(x==py)break;
sum-=(LL)(py-x);
mx[pre]=px-1,py=x;
}
else
{
int x=getp(1,py,px,0);
if(x!=-1)x=max(mx[now],p[0][x]+1);
else x=mx[now];
if(x==px)break;
sum-=(LL)(px-x);
mx[pre]=py+1,px=x;
}
now=(now+1)%4;
}
if(sum==(LL)k)puts("Yes");
else puts("No");
return (0-0);
}

CF1236E Alice&UnfairGame

题目描述

A和B两个人在玩游戏。有编号为1到\(n\)的\(n\)个箱子按编号顺序排成一排,有一个箱子里有东西。

游戏要进行\(m\)轮,每轮的流程是:A先把东西移动到和它相邻的箱子里,然后B猜哪个箱子里有东西。一旦B猜中了,游戏就会结束,并且B获胜。

若游戏进行完了第\(m\)轮,则A还可以把东西移动到和它相邻的箱子里一次,之后A胜利。

已知\(n,m\),和B在每一轮会猜测的箱子编号\(a_1,...,a_m\),问有多少对\((x,y)\)满足游戏开始前东西在\(x\)号箱子,游戏结束时东西在\(y\)号箱子,且A胜利。

一行题解

对于同一个起点,合法终点连续=>在有障碍物的平面上行走=>在某时刻走到某点的“人”的起点连续=>线段树维护区间加减

题解

这个人讲得很清楚。

发现在A知道B的猜测序列时,除非\(n=1\),A总有办法赢。

具体的方式是:从随便一个位置出发,如果这一轮B猜的是左边相邻的箱子就往右走或不走,右边同理,如果B猜的是当前箱子就往右或左走,如果都不是就往右或往左或不走。

按这种移动方式,会发现从每个位置出发,能使A赢的结束位置一定是连续的。

所以可以通过求从每个点出发能走到的使A赢的最左、最右位置。

先考虑最右位置。

假设从\(x\)出发,当前位置为\(p\),时刻为\(t\),那么为了尽可能往右走,应该当且仅当\(a_t=p+1\)时不会走,其他时候都会向右走。

可以把这个过程看成在平面上行走:以时刻为横坐标,以位置为纵坐标,一个人一开始在\((0,x)\)出发,对于每个时刻,如果他右上方没有障碍物就往右上走,反之往右走。

这样是\(O(n^2)\)的。

考虑把所有“人”放在一块考虑:有\(n\)个人在平面上行走,\(i\)号人从\((0,i)\)出发,每个人的走法和上面一样。

发现人们走出的路径可能会合并,但不会交叉。也就是说,某时刻在某位置的人们的坐标是连续的,某时刻人们的坐标按编号是单调不降的。

对于坐标为\((i,a_i)\)的障碍物,会挡住走到\((i-1,a_i-1)\)的“人”们。可以二分出这一段“人”的编号区间。在下一个时刻,除了这个编号区间的人以外,所有人纵坐标+1。

可以用线段树维护当前人们走到的位置的纵坐标。

注意人们不能走出去,因此可以设置\((1,n+1),(2,n+1),...,(m,n+1)\)这些额外的障碍物。

对于最左位置,可以看成把序列翻转后的最右位置。

时间复杂度\(O((n+m)log\space n)\)。

代码

#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#define rep(i,x,y) for(register int i=(x);i<=(y);++i)
#define dwn(i,x,y) for(register int i=(x);i>=(y);--i)
#define view(u,k) for(int k=fir[u];~k;k=nxt[k])
#define LL long long
#define maxn 100007
#define ls (u<<1)
#define rs (u<<1|1)
#define mi ((l+r)>>1)
using namespace std;
int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)&&ch!='-')ch=getchar();
if(ch=='-')f=-1,ch=getchar();
while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return x*f;
}
void write(LL x)
{
if(x==0){putchar('0'),putchar('\n');return;}
int f=0;char ch[20];
if(x<0)putchar('-'),x=-x;
while(x)ch[++f]=x%10+'0',x/=10;
while(f)putchar(ch[f--]);
putchar('\n');
return;
}
int n,a[maxn],m,ans[2][maxn];
LL Ans;
int mn[maxn<<2],mx[maxn<<2],mk[maxn<<2];
void pu(int u){mn[u]=min(mn[ls],mn[rs]),mx[u]=max(mx[ls],mx[rs]);}
void build(int u,int l,int r)
{
mk[u]=0;
if(l==r){mx[u]=mn[u]=l;return;}
build(ls,l,mi),build(rs,mi+1,r),pu(u);return;
}
void mark(int u,int k){mn[u]+=k,mx[u]+=k,mk[u]+=k;}
void pd(int u){if(mk[u])mark(ls,mk[u]),mark(rs,mk[u]),mk[u]=0;}
void add(int u,int l,int r,int x,int y,int k)
{
if(x<=l&&r<=y){mark(u,k);return;}
pd(u);
if(x<=mi)add(ls,l,mi,x,y,k);
if(y>mi)add(rs,mi+1,r,x,y,k);
pu(u);return;
}
int askl(int u,int l,int r,int x)//max,<x
{
if(l==r)return mx[u]<x?l:l-1;
pd(u);
if(mn[rs]<x)return askl(rs,mi+1,r,x);
return askl(ls,l,mi,x);
}
int askr(int u,int l,int r,int x)//min,>x
{
if(l==r)return mx[u]>x?l:l+1;
pd(u);
if(mx[ls]>x)return askr(ls,l,mi,x);
return askr(rs,mi+1,r,x);
}
int ask(int u,int l,int r,int x)
{
if(x<=l&&r<=x){return mx[u];}
pd(u);
if(x<=mi)return ask(ls,l,mi,x);
return ask(rs,mi+1,r,x);
}
void work(int f)
{
build(1,1,n);
rep(i,1,m+1)
{
int l2=askl(1,1,n,n),r2=n;
if(i<=m)
{
int l=askl(1,1,n,a[i]-1),r=askr(1,1,n,a[i]-1);
if(l+1<=r-1)add(1,1,n,l+1,r-1,-1);
}
mk[1]++;
if(l2+1<=r2)add(1,1,n,l2+1,r2,-1);
}
rep(i,1,n)ans[f][i]=ask(1,1,n,i);
}
int main()
{
n=read(),m=read();
rep(i,1,m)a[i]=read();
work(0);
rep(i,1,m)a[i]=n-a[i]+1;
work(1);
reverse(ans[1]+1,ans[1]+n+1);
rep(i,1,n)ans[1][i]=n-ans[1][i]+1;
rep(i,1,n)Ans+=max(0ll,(LL)(ans[0][i]-ans[1][i]+1));
write(Ans);
return 0;
}

并不对劲的CF1236D&E:Alice&Doll&UnfairGame的更多相关文章

  1. 【CF1236D】Alice and the Doll(set)

    题意:给定一个n*m的网格,其中k格有障碍 周驿东从(1,1)出发面朝右,每次行动前他可以选择顺时针旋转90度或不旋转,然后向自己朝向的位置走1格 问他能否不重复不遗漏的走过所有非障碍格 n,m,k& ...

  2. [CF1236D] Alice and the Doll - 模拟,STL

    [CF1236D] Alice and the Doll Description \(N \times M\)网格,有 \(K\) 个格子里有障碍物.每次经过一个格子的时候只能直走或者右转一次.初态在 ...

  3. Codeforces 1236D. Alice and the Doll

    传送门 注意到每个位置只能右转一次,首先考虑如果图没有障碍那么显然要走螺旋形的 然后现在有障碍,容易发现对于某个位置如果既可以直走又可以右转,那么一定会选择直走 因为如果转了以后就一定没法走到原本直走 ...

  4. Codeforces Round #593 (Div. 2) D. Alice and the Doll

    题目:http://codeforces.com/problemset/problem/1236/D思路:机器人只能按照→↓←↑这个规律移动,所以在当前方向能够前进的最远处即为界限,到达最远处右转,并 ...

  5. ZOJ 3633 Alice's present 倍增 区间查询最大值

    Alice's present Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/contest/vi ...

  6. ZOJ 3633 Alice's present RMQ

     Alice's present Description As a doll master, Alice owns a wide range of dolls, and each of them ha ...

  7. [LeetCode] Russian Doll Envelopes 俄罗斯娃娃信封

    You have a number of envelopes with widths and heights given as a pair of integers (w, h). One envel ...

  8. (HDU 5558) 2015ACM/ICPC亚洲区合肥站---Alice's Classified Message(后缀数组)

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5558 Problem Description Alice wants to send a classi ...

  9. 2016中国大学生程序设计竞赛 - 网络选拔赛 J. Alice and Bob

    Alice and Bob Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) ...

随机推荐

  1. ICEM—二维混合网格对齐节点

    原视频下载地址: https://pan.baidu.com/s/1bpnjfT9 密码: jeuv

  2. HearthAgent A Hearthstone agent

    http://www.intelligence.tuc.gr/~robots/ARCHIVE/2015w/Projects/LAB51326833/download.html The project ...

  3. Python 基础学习的几个小例子

    最近在研究动态脚本语言 Python , 出于对其语言精简度的喜欢及大学时期对 matlab 这样的数学领域语言的怀念, 再加上笔者是C++起家,Python中所涉及的del机制与特殊方法重载(类比于 ...

  4. error:Cannot pull with rebase

    原文文链接:https://blog.csdn.net/u012385190/article/details/70670213git 执行git pull –rebase报错误如下: error: C ...

  5. 生成要发送到社区的内核补丁时如何指定发布的版本号(v2,v3...)?

    1. 生成一个补丁 git format-patch --subject-prefix=v2 -1 那么生成的patch文件就会有如下类似的信息: Subject: [v2] your descrip ...

  6. java+上传大文件

    在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 先说下要求: PC端全平台支持,要求支持Windows,Mac,Linux 支持所 ...

  7. SQL Server 高级函数汇总【转】

    看到一个帖子,博主收集的很全,里面涵盖了一些常用的内置函数,特此收藏下: 原文链接:https://blog.csdn.net/wang1127248268/article/details/53406 ...

  8. PHP初中高级学习在线文档下载

    收集了一些框架的学习文档与手册,视频教程,给大家带来了更多的方便,只要收藏与保存于百度云盘就好了,省去了网上到处寻找的时间!大家有需要就收藏保存起来吧! 如果不能下载请到群内获取新的下载地址 QQ群 ...

  9. VS自定义代码块Code Snippet

    一  .简述 我们在开发当中,避免不了一些重复的开发工作,在你漫长的开发以及学习当中,你会发现有这么一部分代码是你时常会使用到的.我想这个工具也是针对这个原因出来的吧,它就是预先把你需要的这部分代码的 ...

  10. windows下redis配置密码

    redis安装后目录如下: 最简单的启动方式是直接双击redis-server.exe 如果要设置密码,首先打开配置文件,要注意的是这两个都是配置文件,记住你改的是哪一个,不放心的可以两个都改. 然后 ...