题目链接:https://www.zhixincode.com/contest/1/problem/A?problem_id=2

题目大意 初始在A区的S点,在AB两个区域上有一些需要到达的点,在AB区域上只能在给定的特殊点转向或者到另一个区域,其余的点只能按照之间的方向继续行走。穿越区域需要花费代价k,从a点到b点花费代价abs(a-b),初始点S可以选择一个方向行走。

 

题解思路:首先我们需要构建两个区间,a区间和b区间,区间的端点都为可以转向的点,区间包含了所有需要到达的点,假如存在b区间,那么b区间一定包含于a区间,因为我们初始的s在A区域上,先从A区域走,走到a区间的一个边界然后翻到B区域,这样肯定要满足b区间比a区间要小 才在贪心策略上最优。

所以在构建完ab区间后要满足b比a小

需要注意的是,在构建a区间的时候,初始的s点也是可以转向的,虽然这个点不一定可以翻越,在图中第三种情况里也是可以作为区间端点的,在构造a区间的时候需要把s也加入到vec中排序,然后二分找一下。

主要分类就是图中的几种情况,合并起来就是区间+到区间的距离+2k(如果穿越的话)

ccpc wanna fly day1 A 机器人

 

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
const int maxn=1e6+5;
using namespace std;
pair<int,int>a[maxn];
vector<int>vec;
int main()
{
    int n,r,m,k,s,p;
    cin>>n>>r>>m>>k>>s;//区间长度为n r个需要到的个点 m个特俗点 穿越代价为k 起始点为s
    vec.push_back(1);vec.push_back(n);
    int tem;
    for(int i=1;i<=r;i++)//要到的点
    {
        cin>>a[i].first>>a[i].second;
    }
    for(int i=1;i<=m;i++)//特殊点
    {
        cin>>tem;
        vec.push_back(tem);
    }
    sort(vec.begin(),vec.end());
    int al=n,ar=1,bl=n,br=1;
    int flag=0;
    for(int i=1;i<=r;i++)
    {
        if(a[i].second)
        {
            flag=1;
            bl=min(bl,*(upper_bound(vec.begin(),vec.end(),a[i].first)-1));//第一个小于等于
            br=max(br,*(lower_bound(vec.begin(),vec.end(),a[i].first)));//第一个大于等于
        }
    }
    vec.push_back(s);//s点可以作为a的转向点
    sort(vec.begin(),vec.end());
    for(int i=1;i<=r;i++)
    {
        if(!a[i].second)
        {
            al=min(al,*(upper_bound(vec.begin(),vec.end(),a[i].first)-1));//第一个小于等于
            ar=max(ar,*(lower_bound(vec.begin(),vec.end(),a[i].first)));//第一个大于等于
        }
    }
    al=min(al,bl);ar=max(ar,br);//保证a区间要包含b区间
    //cout<<al<<' '<<ar<<' '<<bl<<' '<<br<<endl;
    if(!flag)
    {
        cout<<2*(ar-al+max(0,al-s)+max(0,s-ar))<<endl;
    }
    else
    {
        cout<<2*(k+ar-al+max(0,al-s)+max(0,s-ar))<<endl;
    }

    return 0;
}

 

相关文章: