ARC101F Robots and Exits 树状数组

有 $ n $ 个机器人和 $ m $ 个出口。这 $ n $ 个机器人的初始位置是 $ a_1,a_2.....a_n $ ,这 $ m $ 个出口的位置是 $ b_1,b_2.....b_m $ 。你每次可以让所有机器人往左走一步或往右走一步。当一个机器人所在的位置有一个出口时,这个机器人就会从这个出口出去。问你有多少种让机器人全部离开的方案。两种方案不同当且仅当有至少一个机器人从不同的出口出去。 $ n,m≤100000 $



$ solution: $

首先我们可以将所有在最左端出口以左,最右端出口以右的机器人删掉,他们的最终出口只有一个,不影响答案。

然后我们考虑对于机器人 $ i $ ,它到左边距离它最近的出口的距离为 $ x_i $ ,如果我们往左移的距离超过 $ x_i $ 机器人就会掉进左边这个出口 ;同理设它到右边距离它最近的出口的距离为 $ y_i $ ,如果我们往右移的距离超过 $ y_i $ 机器人就会掉进右边这个出口。为了方便理解,我们先将它放到平面上:

我们考虑这个二维平面的意义:如果我们单纯将机器人左移或右移一个单位,会做很多无用功。但是我们发现,如果我们设 $ (l,r) $ 表示我向左移的最远 $ l $ 步向右移的最远 $ r $ 步 ,我们只有将最远步数向外扩展+1,才可能会有机器人掉进出口。而我们如果将这个步数也放到平面上,因为 $ l $ 和 $ r $ 的不断增大,会产生一个折线(如下图一)。我们发现这个折线如果经过某些平行于 $ y $ 轴的直线,它所代表的实际意义就是:对应的机器人会在这条折线与直线相交的时候掉入左边的出口(即当 $ l==x_i $ 时机器人 $ i $ 到达左边出口)

同理,我们发现这个折线如果经过某些平行于 $ x $ 轴的直线,其实际意义为:对应的机器人会在这条折线与直线相交的时候掉入右边的出口(即当 $ r==y_i $ 时机器 $ i $ 到达右边的出口)(如下图二)

我们再仔细观察一下这个平面所能带给我们的信息,我们发现这样一个性质:折线单调递增。折线通过竖直的直线时(继续上图一),这个点一定在折线上方对应的机器人从左边出口掉落;折线通过水平的直线时(继续上图二),这个点一定在折线下方对应的机器人从右边出口掉落。这是一个十分有用的性质!因为我们的所求的方案不同,当且仅当有至少一个机器人从不同的出口出去,我们将这个题意转入平面中,意思就是折线上下的点集不同

然后我们的DP就要登场辣!(好吧,请忽略这个中二病语气)首先我们要设出状态,我们可以根据折线每一次向上走设出状态(只有向上走越过某一条直线才会改变状态),我们设 $ f[i] $ 表示折线最后一次向右转后第一个包括的点为 $ i $ 的所有方案(这个点是所有折线下面的点里最高的点,有多个最高就取最左端的点)。这样设状态不会重复我们需要仔细思考这样设状态的意义。(这个状态转移是比较难想到的!因为要不重不漏)

然后我们考虑怎么转移:以下图为例,我们的 $ f[i] $ 是包括了点 $ i $ 的,我们如果让折线在包括点 $ i $ 后将状态转移到 $ j $ ,我们必须保证移动过程中 $ j $ 是折线最后一次向右转后第一个包括的点。于是我们可以继续向右移直到这个点 $ j $ 的竖直直线,我们立即向上转,再用折线从 $ j $ 水平直线越过后立即向右转。如下图: $ f[1] $ 可以转移到 $ f[5],f[4],f[3] $ ,所有在它右上方的点都可以!(这样的实际意义就是,我们原本 $ f1 $ 中在点1直接向右转就不往上了,意义是点345都从左边出口出去,现在我们用折线包括后点345分别变成从右边出口出去!)

同理,我们的 $ f2 $ 也可以转移到所有在它右上方的点!

于是我们发现转移方程其实就是这样:每个点的状态可以通过它左下方的点转移过来(我们上面讨论的是转移过去)

$ f[i]=f[j]+1 \quad (x_i>x_j,y_i>y_j) $

这个可以用树状数组维护,我们先将所有点按照纵坐标为第一关键字从低到高排序横坐标为第二关键字从右到左(从右到左是为了方便转移不重复,注意上面转移方程是两个小于号,我们平面里同一高度左边的点不能转移到右边,它不满足保证移动过程中 $ i $ 是折线最后一次向右转后第一个包括的点,第一个仍旧是原来那一个)。具体实现时,我们直接按顺序枚举所有点的状态,然后按照横坐标将每个点 $ i $ 对应的 $ f[i] $ 存进树状数组,因为我们的枚举的高度从低到高,那么后面我查询时直接在树状数组上查找横坐标-1的前缀和,即可完成转移!



$ code: $

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set> #define ll long long
#define db double
#define rg register int using namespace std; const int mod=1e9+7;//998244353; int n,m;
int tt,ans=1; //注意赋了初值1
int a[500005];
int b[500005];
int k[500005]; //离散化
int f[500005]; //计数
int tr[500005]; //树状数组 struct su{
int x,y;
inline bool operator <(const su &z)const{
if(y==z.y)return x>z.x;
return y<z.y;
}
}s[500005]; inline int qr(){
register char ch; register bool sign=0; rg res=0;
while(!isdigit(ch=getchar()))if(ch=='-')sign=1;
while(isdigit(ch))res=res*10+(ch^48),ch=getchar();
if(sign)return -res; else return res;
} inline void add(int x,int v){ //树状数组加入
for(;x<=tt;x+=x&-x) (tr[x]+=v)%=mod;
} inline int ask(int x){ //树状数组查询
rg res=0;
for(;x;x-=x&-x) (res+=tr[x])%=mod;
return res;
} int main(){
//freopen("robot.in","r",stdin);
//freopen("robot.out","w",stdout);
n=qr(); m=qr();
for(rg i=1;i<=n;++i) a[i]=qr();
for(rg i=1;i<=m;++i) b[i]=qr(); //已经按顺序排序
for(rg i=1,j=1;i<m&&j<=n;++i){
while(j<=n&&a[j]<=b[i])++j; //找到中间的第一个机器人
if(j>n)break;
while(j<=n&&a[j]<b[i+1]){ //遍历所有在中间的机器人
k[++tt]=a[j]-b[i]; //k数组是用来离散化的
s[tt]=su{k[tt],b[i+1]-a[j]}; ++j; //记录左右距离
}
} sort(k+1,k+tt+1); //离散化
for(rg i=1;i<=tt;++i)
s[i].x=lower_bound(k+1,k+tt+1,s[i].x)-k; //离散化
sort(s+1,s+tt+1); //按纵坐标从小到大,横坐标从大到小
for(rg i=1;i<=tt;++i){
if(s[i].x==s[i-1].x&&s[i].y==s[i-1].y)continue; //去重!
f[i]=(ask(s[i].x-1)+1)%mod; //只有横坐标比它小的才可以转移
ans=(ans+f[i])%mod; //计入答案
add(s[i].x,f[i]); //加入树状数组
}
printf("%d\n",ans);
return 0;
}

【ARC101F】Robots and Exits 树状数组优化DP的更多相关文章

  1. 【题解】ARC101F Robots and Exits(DP转格路+树状数组优化DP)

    [题解]ARC101F Robots and Exits(DP转格路+树状数组优化DP) 先删去所有只能进入一个洞的机器人,这对答案没有贡献 考虑一个机器人只能进入两个洞,且真正的限制条件是操作的前缀 ...

  2. HDU 6240 Server(2017 CCPC哈尔滨站 K题,01分数规划 + 树状数组优化DP)

    题目链接  2017 CCPC Harbin Problem K 题意  给定若干物品,每个物品可以覆盖一个区间.现在要覆盖区间$[1, t]$. 求选出来的物品的$\frac{∑a_{i}}{∑b_ ...

  3. Codeforces 946G Almost Increasing Array (树状数组优化DP)

    题目链接   Educational Codeforces Round 39 Problem G 题意  给定一个序列,求把他变成Almost Increasing Array需要改变的最小元素个数. ...

  4. LUOGU P2344 奶牛抗议 (树状数组优化dp)

    传送门 解题思路 树状数组优化dp,f[i]表示前i个奶牛的分组的个数,那么很容易得出$f[i]=\sum\limits_{1\leq j\leq i}f[j-1]*(sum[i]\ge sum[j- ...

  5. 【题解】Music Festival(树状数组优化dp)

    [题解]Music Festival(树状数组优化dp) Gym - 101908F 题意:有\(n\)种节目,每种节目有起始时间和结束时间和权值.同一时刻只能看一个节目(边界不算),在所有种类都看过 ...

  6. Codeforces 909C Python Indentation:树状数组优化dp

    题目链接:http://codeforces.com/contest/909/problem/C 题意: Python是没有大括号来标明语句块的,而是用严格的缩进来体现. 现在有一种简化版的Pytho ...

  7. BZOJ3594: [Scoi2014]方伯伯的玉米田【二维树状数组优化DP】

    Description 方伯伯在自己的农田边散步,他突然发现田里的一排玉米非常的不美. 这排玉米一共有N株,它们的高度参差不齐. 方伯伯认为单调不下降序列很美,所以他决定先把一些玉米拔高,再把破坏美感 ...

  8. Codeforces 629D Babaei and Birthday Cake(树状数组优化dp)

    题意: 线段树做法 分析: 因为每次都是在当前位置的前缀区间查询最大值,所以可以直接用树状数组优化.比线段树快了12ms~ 代码: #include<cstdio> #include< ...

  9. BZOJ 3594: [Scoi2014]方伯伯的玉米田 (二维树状数组优化DP)

    分析 首先每次增加的区间一定是[i,n][i,n][i,n]的形式.因为如果选择[i,j](j<n)[i,j](j<n)[i,j](j<n)肯定不如把后面的全部一起加111更优. 那 ...

随机推荐

  1. 【linux】杀掉进程命令

    1.找到对应的进程 通过端口查找 lsof -i:端口号 netstat -tunlp | grep 端口   lsof -i:9500   netstat -tunlp | grep 9500 2. ...

  2. 阶段3 1.Mybatis_01.Mybatis课程介绍及环境搭建_04.mybatis概述

  3. Java之Swing体系——制作自己的登录界面

    我们制作登陆界面是简单的图形模式,并不具备其他功能: 这里使用两个库,如下: javax.swing.*; java.awt.*; 构造窗体对象要用到很多类,废话不多,直接代码~ package co ...

  4. Django 基于角色的权限控制

    有一种场景, 要求为用户赋予一个角色, 基于角色(比如后管理员,总编, 编辑), 用户拥有相应的权限(比如管理员拥有所有权限, 总编可以增删改查, 编辑只能增改, 有些页面的按钮也只有某些角色才能查看 ...

  5. Lesson 1 A puma at large

    spot (v) 看出,发现 oblige (v) 使...感到必须:obliged (adj)必须的, feel obliged to do sth. 感到不得不做某事 ==have to.eg:E ...

  6. Github 上 Star 最多的个人 Spring Boot 开源学习项目(三)

    网上连载了 Spring Boot 系列文章 这个开源项目就是 spring-boot-examples ,这是一个专注帮助初学者学习 Spring Boot 的开源项目,里面分享了各种场景下 Spr ...

  7. CentOS7 安装dotnet sdk 2.1.401 的简单办法

    1. 下载 linux版本的tar包 路径为: https://dotnet.microsoft.com/download/thank-you/dotnet-sdk-2.1.401-linux-x64 ...

  8. [luogu5339] [TJOI2019]唱、跳、rap和篮球(容斥原理+组合数学)(不用NTT)

    [luogu5339] [TJOI2019]唱.跳.rap和篮球(容斥原理+组合数学)(不用NTT) 题面 略 分析 首先考虑容斥,求出有i堆人讨论的方案. 可以用捆绑法,把每堆4个人捆绑成一组,其他 ...

  9. 分布式均匀算法--hash性一致算法--hash slot(转)

    目录 1.redis cluster介绍 2.最老土的hash算法和弊端(大量缓存重建) 3.一致性hash算法(自动缓存迁移)+虚拟节点(自动负载均衡) 不用遍历    -->   hash算 ...

  10. app接口开发

    最近一段时间一直在做APP接口,总结一下APP接口开发过程中的注意事项: 1.效率:接口访问速度 APP有别于WEB服务,对服务器端要求是比较严格的,在移动端有限的带宽条件下,要求接口响应速度要快,所 ...