AtCoder - arc101_d Robots and Exits

63 阅读3分钟

 将机器人 i 距离其左出口和右出口的距离记成x_i , y_i ,如果有两头端点的一些机器人只有左出口或者只有有出口,就不记录x_i 和 y_i 了,因为他们只有一个出口供选择,不会影响最终出口选择方案的数量

记机器人们(相对自身原来位置)向左走的最大距离为x,向右走的最大距离为y,则不管具体行走路线是什么样的,要么x增加1,要么y增加1,这两种情况才有可能造成机器人走向出口的实质性改变

好的,以上实际上是铺垫,关键的步骤是将x_i y_i和x,y放入平面直角坐标系中,接下来的内容用手写的方式展现

​ 分隔线

​编辑

然后还有一些实现的细节技巧,两个机器人的x_i=x_j,y_i=y_j,这种情况只算一个机器人,因为坐标范围很大,可以将点按照先x小后y大的方式排序,这样使用动态规划数组dp[h],h代表点的y坐标,每次更新dp[h]=dp[h1]的和(h1<h)+1就可以保证x_j<x_i并且y_y<y_i,然后因为h坐标也很大,所以将h离散化后实现求前缀和,以下的程序用线段树实现,用树状数组也可以

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;

#define ll long long

const int maxn=1e5+5,mod=1e9+7;
int n,m,botcnt,ycnt;
int a[maxn],b[maxn],y[maxn];
ll tree[maxn<<2];

struct Robot{
    int x,y;
    bool operator < (const Robot &rhs) const {
        if(x==rhs.x) return y>rhs.y;
        return x<rhs.x;
    }
    bool operator == (const Robot &rhs) const {
        return x==rhs.x && y==rhs.y;
    }
}bot[maxn];

inline int ls(int x) {return x<<1;}
inline int rs(int x) {return (x<<1)|1;}

void push_up(int p){
    tree[p]=tree[ls(p)]+tree[rs(p)];
}


void update(int p,int pl,int pr,int L,int R,ll d){
    if(pl>=L && pr<=R){
        tree[p]=(tree[p]+d)%mod;
        return;
    }
    int mid=(pl+pr)>>1;
    if(L<=mid) update(ls(p),pl,mid,L,R,d);
    if(R>mid) update(rs(p),mid+1,pr,L,R,d);
    push_up(p);
}

ll query(int p,int pl,int pr,int L,int R){
    if(pl>=L && pr<=R){
        return tree[p];
    }
    ll res=0;
    int mid=(pl+pr)>>1;
    if(L<=mid) res=(res+query(ls(p),pl,mid,L,R))%mod;
    if(R>mid) res=(res+query(rs(p),mid+1,pr,L,R))%mod;
    return res;
}

int main()
{
    ios::sync_with_stdio(0);cin.tie(0);

    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=m;i++) cin>>b[i];

    stable_sort(b+1,b+1+m);
    for(int i=1;i<=n;i++){
        if(a[i]<b[1] || a[i]>b[m]) continue;
        int k=lower_bound(b+1,b+1+m,a[i])-b-1;
        bot[++botcnt].x=a[i]-b[k];
        bot[botcnt].y=b[k+1]-a[i];
        y[++ycnt]=bot[botcnt].y;
    }

    stable_sort(bot+1,bot+1+botcnt);
    botcnt=unique(bot+1,bot+1+botcnt)-bot-1;

    stable_sort(y+1,y+1+ycnt);
    ycnt=unique(y+1,y+1+ycnt)-y-1;


    for(int i=1;i<=botcnt;i++){
        int k=lower_bound(y+1,y+1+ycnt,bot[i].y)-y;
        if(k>1)
            update(1,1,ycnt,k,k,(query(1,1,ycnt,1,k-1)+1)%mod);
        else
            update(1,1,ycnt,k,k,1);
    }
    cout<<(query(1,1,ycnt,1,ycnt)+1)%mod<<"\n";
    return 0;
}