[ARC101D] Robots and Exits 题解

建模+树状数组优化 DP

这个建模真的神奇/bx

Statement

AT4353 [ARC101D] Robots and Exits - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

Solution

容易发现题目所指的方案和具体如何操作无关,只和每个机器人进的是 左/右 有关

显然,可以直接忽略掉坐标在最左边的坑的左边的机器人和右边的

可以想到使用一个二元组 \((x,y)\) 表示一个机器人,其中 \(x,y\) 分别表示当前机器人到左/右的距离

把这些点放在平面直角坐标系上,经过头脑风暴,发现题目成为了这样一个模型:

\((0,0)\) 出发,每一步可以向上/右走,一直走到超过 \((x_{max},y_{max})\)

对于形成的这条折线,如果一个点在折线下方,那么我认为这个机器人掉入了右边,否则掉进了左边

为避免歧义,可以把每个点 \((x,y)\to (x+0.5,y+0.5)\)

正确性可以这样理解,我这个折线一直走,对于一个点而言,只要折线在自己和原点围成的这个矩形内,那么自己就没有掉进洞,反正题目不管我具体操作。而一旦这条线从这个矩形的上方突破,那么我掉进了右边,对应这个点在折线下方

\(f_i\) 表示折线经过前 \(i\) 个点的方案数,转移式子为 \(f_i=\sum_{x_j<x_i \& y_j<y_i} f_j+1\)

树状数组优化一下就是 \(O(n\log n)\)

Code

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+5;
const int mod = 1e9+7;

char buf[1<<23],*p1=buf,*p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
int read(){
	int s=0,w=1; char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();} 
	while(isdigit(ch))s=s*10+(ch^48),ch=getchar();
	return s*w;
} 
void inc(int &a,int b){a=a>=mod-b?a-mod+b:a+b;}
void dec(int &a,int b){a=a>=b?a-b:a+mod-b;}

struct BIT{
	int c[N];
	int lowbit(int x){return -x&x;}
	void add(int x,int v){for(;x<N;x+=lowbit(x))inc(c[x],v);}
	int ask(int x){int r=0;for(;x;x-=lowbit(x))inc(r,c[x]);return r;}
}bit;
struct Data{int x,y;}a[N];
int x[N],y[N],L[N],R[N],t[N];
int n,m,cnt,ans,tot;

signed main(){
	n=read(),m=read();
	for(int i=1;i<=n;++i)x[i]=read();
	for(int i=1;i<=m;++i)y[i]=read();
	y[0]=-1e9,y[m+1]=2e9;
	for(int i=1;i<=n;++i)
		L[i]=upper_bound(y,y+m+2,x[i])-y-1,
		R[i]=lower_bound(y,y+m+2,x[i])-y;
	for(int i=1;i<=n;++i)if(L[i]!=0&&R[i]!=m+1)
		a[++cnt]=(Data){x[i]-y[L[i]],y[R[i]]-x[i]},t[cnt]=y[R[i]]-x[i];
    sort(t+1,t+cnt+1),tot=unique(t+1,t+cnt+1)-t-1;
    for(int i=1;i<=cnt;++i)a[i].y=lower_bound(t+1,t+cnt+1,a[i].y)-t+1;
	sort(a+1,a+1+cnt,[](Data p,Data q)
		{return p.x==q.x?p.y>q.y:p.x<q.x;});
    bit.add(1,1);
	for(int i=1;i<=cnt;++i){
        if(a[i].x==a[i-1].x&&a[i].y==a[i-1].y)continue;
		bit.add(a[i].y,bit.ask(a[i].y-1));
	}
	printf("%d\n",bit.ask(N-1));
	return 0;
} 
posted @ 2022-04-10 18:56  _Famiglistimo  阅读(52)  评论(0编辑  收藏  举报