首页 > 其他 > 详细

【NOIP模拟10-21】的士碰撞

时间:2017-10-22 00:58:56      阅读:152      评论:0      收藏:0      [点我收藏+]

Description

 ??辆车在一条数轴上,车的编号为1到??。编号为??的车坐标为??[??],初始方 向为??????[??](左或右),初始位置两两不同。每辆车每个时刻行走距离为1。两辆 车相碰时,会调转方向,继续行走,掉头不消耗时间。现在车子开始朝其方向行 驶,同一个坐标允许有多辆车。现在有??个询问,给出??, ??,询问过了??时刻后, 编号为??的车的坐标的绝对值。 

Input Format

输入文件名为collision.in。 首先输入??, ??。 接下来??行,每行两个整数??[??], ??????[??],若??????[??] = 0,表示车子向左行走,若 ??????[??] = 1,表示车子向右行走。 接下来??行,每行两个整数??, ??,询问时刻??时编号为??的车的坐标。 

Output Format

输出文件名为collision.out。 对于每个询问,输出一个整数,代表编号为??的车的坐标。

Sample Input & Sample Output

【输入输出样例1】 collision.in collision.out 5 5 1 1 4 1 2 0 7 1 11 0 5 1 10 2 7 3 8 4 20 5 3 1 8 12 27

【输入输出样例2】 collision.in collision.out 20 15 31116973 1 721410312 0 152891538 1 55434456 0 903968 1 34492580 0 97565125 0 78559065 1 191708700 0 335941230 0 526621966 1 25622049 38331852 977130985 662422758 171848754 220003868 5474029 533404717 11069472 1056101384 524968026 326917138168159348 1 457798506 1 160026937 1 76511872 1 247171016 1 48722268 0 159552820 0 701333640 0 434868520 1 143857480 13 821356724 11 132436670 1 20249229 11 504666 16 138701034 19 339607872 1 184664000 13 80827802 15 625365533 5 668115287 6 93821572 7 175176488 5 438184710 1 71279702 12 237940668 420617936 689224277

Hint

【数据规模与约定】 对于30%的数据,max(??) ×?? ≤ 107 另外有30%的数据,??, ?? ≤ 1000 对于100%的数据,??, ?? ≤ 100000,0 ≤ ??[??] ≤ 109 ,?? ≤ 109 , ??????[??] ∈ {0,1}

思路

首先的士碰撞之后会掉头,
在这里我们可以理解为两辆车互换了编号,
然后继续前行。
那如何求出编号为x的最终位置呢?
这里可以用二分答案,
要用二分,我们需要单调。
因为在坐标轴上,从小到大,很显然是单调的。
如何验证答案,

技术分享
如图,我们可以发现箭头变大了一辆车的rank是不会改变的,
因为大家的速度是一致的,不存在追及,而且相遇后会掉头,
所以它会一直在原来位置的前一辆车和后一辆车中间。
我们把车按照位置排一次序,
然后我们二分一个位置,使这个位置的rank与原来的相等;
询问这个位置的rank直接for循环一遍会超时,
所以我们继续二分,先按照方向和位置,把车分成A、B两组,
分别表示向右走和向左走的车的原始位置。
然后分别二分找出A中与B中比X小的车数量,两者相加就是X的rank,即可验证答案.

 

#include<cstdio>
#include<algorithm>
#define LL long long

int n,q,tota,totb;
LL a[100005],b[100005];
struct node
{
    int pos,rank,num;
}nod[100005];

bool cmp(node x,node y)
{
    return x.pos<y.pos;
}

int Count(LL a[],int len,LL x)
{
    int res=0,l=1,r=len;
    while (l<=r)
    {
        int mid=(l+r)>>1;
        if (a[mid]<=x) res=mid,l=mid+1;
        else r=mid-1;
    }
    return res;
}

int main()
{
    scanf("%d%d",&n,&q);
    for (int i=1;i<=n;i++)
    {
        int dir;
        scanf("%d%d",&nod[i].pos,&dir);
        nod[i].num=i;
        if (dir) a[++tota]=nod[i].pos;
        else b[++totb]=nod[i].pos;
    }
    std::sort(nod+1,nod+n+1,cmp);
    for (int i=1;i<=n;i++) nod[nod[i].num].rank=i;    
    std::sort(a+1,a+tota+1);
    std::sort(b+1,b+totb+1);
    for (int i=1;i<=q;i++)
    {
        int tim,num,ans=0;
        scanf("%d%d",&tim,&num);
        num=nod[num].rank;
        LL l=std::min(a[1]+tim,b[1]-tim),r=std::max(a[tota]+tim,b[totb]-tim);
        while (l<=r)
        {
            LL mid=(l+r)>>1;
            int count=Count(a,tota,mid-tim)+Count(b,totb,mid+tim);
            if (count>=num) ans=mid,r=mid-1;
            else l=mid+1;
        }
        printf("%d\n",abs(ans));
    }
}

 

【NOIP模拟10-21】的士碰撞

原文:http://www.cnblogs.com/Shawn7xc/p/7707449.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!