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. leetcode 113 path Sum II 路径和

    递归先序遍历+vector<int>容器记录路径 /** * Definition for a binary tree node. * struct TreeNode { * int va ...

  2. java网络通信:同步阻塞式I/O模型(BIO)

    缺点:一个线程只能处理一个客户端连接 服务端: public class TimeServer { public static void main(String[] args) throws IOEx ...

  3. Matlab——图形绘制——三维立体图形 剔透玲珑球 动态图——彗星状轨迹图

    三维绘图函数 三维绘制工具 函数view 实例:三维螺旋线 >> t=:pi/:*pi; plot3(sin(t),cos(t),t) grid %添加网格  plot3可以画出空间中的曲 ...

  4. 【Linux开发】【Qt开发】嵌入式Qt程序使用触屏或USB鼠标方式

    上文<嵌入式Qt开发-移植到ARM开发板 >介绍了Qt程序的移植,本文再说下如何使开发板Qt程序使用触摸屏或USB方式进行交互. 之前刚把一个qt程序移植到arm板上成功运行显示时就开心的 ...

  5. kafka学习(五)

    kafka可靠的数据传递   kafka可靠性保证 ACID 是关系型数据库保证数据的规范,指的是原子性,一致性,隔离性和持久性,这是数据库给出的可靠性保证.   kafka给出的保证是什么? 1.k ...

  6. [DS+Algo] 002 一维表结构

    目录 1. 顺序表 1.1 分类 1.2 实现方式 1.3 扩容问题 1.4 操作 2. 链表 2.1 分类 2.2 链表相关操作 2.3 链表 VS 顺序表 3. 关于代码实现 1. 顺序表 1.1 ...

  7. Linux cat 多行写入文件防止变量替换

    Linux cat 多行写入文件防止变量替换  问题描述 对多个变量及多行输出到文件,存在变量自动替换,当使用cat<<EOF不想对内容进行变量替换.命令替换.参数展开等 问题解决 转义特 ...

  8. Element-ui 使用详细介绍

    一.后台搭建 使用 vue-admin-template 来快速搭建后台管理,它包含了 Element UI & axios & iconfont & permission c ...

  9. JZOJ2678 树B

    题 Description 已知无向连通图G由N个点,N-1条边组成.每条边的边权给定.现要求通过删除一些边,将节点1与另M个指定节点分开,希望删除的边的权值和尽量小,求此最小代价. Input 每个 ...

  10. 使用foreach一次性添加多个单选按钮

    <?php //这个函数创建一个单选按钮 //函数接收一个论据:值 //函数也会让按钮有"黏性"-->记住你是如何填写它的. function create_radio ...