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. Memcached与Memcache区别

    在写这篇文章之前一直对memcache .memcached模糊,相差一个字母,特此总结下: Memcache是什么? Memcache是一个自由和开放源代码.高性能.分配的内存对象缓存系统.用于加速 ...

  2. 18 Flutter仿京东商城项目 商品详情顶部tab切换 顶部下拉菜单 底部浮动导航

    ProductContent.dart import 'package:flutter/material.dart'; import '../services/ScreenAdaper.dart'; ...

  3. [ML] Roadmap: a long way to go

    看上去不错的博文: 机器学习的经典算法一览 (一) 机器学习的经典算法一览 (二)       1.引言 正文将详细介绍传统机器学习算法,基本思想和用途.把问题解决思路和方法应用建议提前到这里的想法也 ...

  4. 每个Xcode开发者应该知道的几个使用技巧

    1.快速打开 快速打开(Open Quickly)命令在Xcode的File菜单中,当然,用快捷键Command+Shift+O会更方便一些.这个命令可以开启一个小窗格用来快速搜索浏览文件.类.算法以 ...

  5. ubuntu默认root密码问题,第一次使用ubuntu需要设置root密码

    http://www.voidcn.com/article/p-yvnoogkc-ng.html 新接触ubuntu(baseondebian)的人,大多会因为安装中没有提示root密码而不太清楚为什 ...

  6. react 组件创建

    /** * 数据屏蔽 * Created by 2016-12-02. */ import React, {Component} from 'react'; export default class ...

  7. Clonezilla克隆还原系统

    简介 Clonezilla是一个专门用来克隆磁盘驱动器的Linux发行版.它可以操作任何你所能想象到的文件系统类型.Clonezilla有两种版本:Live和SE.Live版本与Ubuntu的Live ...

  8. Elasticsearch删除数据操作,你必须知道的一些坑

    前两天有同事打电话问我,说ES删除数据有没有什么坑? 我当时就问,是删索引还是删索引里的数据?她回答说是删数据,我说查出这些数据直接删除就好了,没有什么坑... 后来想想,关于ES数据的删除,之前确实 ...

  9. laravel5.5的定时任务详解(demo)

    原文地址:https://blog.csdn.net/LJFPHP/article/details/80417552

  10. Ubuntu搭建Spring源码环境常见问题

    在一心想要学习Spring框架源码时,我们会遇到很多麻烦的问题.开始本文前,你只需要拥有一个装好IDEA的Ubuntu系统就可以愉快启程了.如果还没有IDEA,可以参考在Ubuntu上安装Intell ...