• 洛谷P3407 散步[分组]


    题目描述

    一条道路上,位置点用整数A表示。

    当A=0时,有一个王宫。当A>0,就是离王宫的东边有A米,当A<0,就是离王宫的西边有A米。

    道路上,有N个住宅从西向东用1-N来标号。每个住宅有一个人。住宅只会存在于偶数整数点。

    该国国王认为,国民体质下降,必须要多运动,于是下命令所有人都必须出门散步。所有的国民,一秒钟可以走1米。每个国民各自向东或者向西走。这些方向你是知道的。命令发出后所有人同时离开家门开始散步。

    然而该国的国民个都很健谈,如果在散步途中两个人相遇,就会停下来交谈。正在走路的人碰到已经停下来的人(重合)也会停下来交谈。一但停下来,就会聊到天昏地暗,忘记了散步。

    现在命令已经发出了T秒,该国有Q个重要人物,国王希望能够把握他们的位置。你能帮他解答吗?

    输入输出格式

    输入格式:

    第一行是3个整数,N,T,Q

    接下来N行,每行两个整数Ai,Ri。Ai是家的坐标,如果Ri是1,那么会向东走,如果是2,向西。数据保证Ai是升序排序,而且不会有两个人初始位置重合。

    接下来Q行,每行一个整数,表示国王关心的重要人物。

    输出格式:

    Q行,每行一个整数,表示这个人的坐标。

    输入输出样例

    输入样例#1:
    6 6 4
    -10 1
    -6 2
    -4 1
    2 1
    6 2
    18 2
    2
    3
    4
    6
    输出样例#1:
    -8
    2
    4
    12

    说明

    20%数据 N<=100,T<=10000

    另外20%数据 N<=5000

    另外20%数据 从最西边数起连续的若干国民全部往东,剩下的全部往西

    100%数据 Ai为偶数,|Ai|<=10^18,|T|<=10^18,1<=Q<=N<=100000.


    只想到部分分

    官方题解:

    为什么数据范围这么奇怪?因为这个范围已经剧透了。

    我们先考虑“从西边数连续的人全部往东,剩下的全部往西”这个。

    我们会发现,他们最后都会集中在一个点上。哪个点?就是中间的那对面对面的中间点。我们只要判断时间内,人能不能走到这个点停下来。于是20分get。

    100分呢?我们是不是可以吧所有人分成若干组,然后每一组分别计算啊?

    例如样例,我们将(认为往东,)往西。他们最终会停在|的地方。

      第一组                   第二组
    (    |    )          (  (     |     )  )
    -10  -8   -6         -4 2     4     6 18

    于是我们就很清楚了。

    那最左边的人向左,最右边的人向右怎么办呢?那就让他走呗,特判一下,反正永远也停不下来。

    想到那20%了,原来扫描然后分组就可以了......................

    //
    //  main.cpp
    //  luogu10r2.2
    //
    //  Created by Candy on 10/15/16.
    //  Copyright © 2016 Candy. All rights reserved.
    //
    
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    const int N=1e5+5;
    inline ll read(){
        char c=getchar();ll x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    ll n,t,Q,a[N],d[N],q[N],ans[N];
    void cal(int l,int r){
        if(l==r) a[l]+=d[l]*t;
        else if(d[l]==-1||d[r]==1)
            for(int i=l;i<=r;i++) a[i]+=d[i]*t;
        else{
            int pos=l;
            while(d[pos+1]==1) pos++;
            ll mid=(a[pos]+a[pos+1])/2;
            for(int i=l;i<=r;i++){
                ll tmp=a[i]+t*d[i];
                if((a[i]<=mid&&tmp>=mid)||(a[i]>=mid&&tmp<=mid)) a[i]=mid;
                else a[i]=tmp;
            }
        }
    }
    int main(int argc, const char * argv[]) {
        n=read();t=read();Q=read();
        for(int i=1;i<=n;i++) {
            a[i]=read(),d[i]=read();
            if(d[i]==2) d[i]=-1;
        }
        for(int i=1;i<=Q;i++) q[i]=read();
        
        int l=1,dir=1;
        for(int i=1;i<=n;i++){
            if(d[i]==1&&dir==-1){
                cal(l,i-1);
                l=i;
                dir=1;
            }
            dir=d[i];
        }
        if(l<=n) cal(l,n);
        for(int i=1;i<=Q;i++) printf("%lld
    ",a[q[i]]);
        return 0;
    }
  • 相关阅读:
    VS2005 GridView操作大全(转载)
    架构与模式
    JS全选与取消
    C#查找指定文件夹下指定后缀名的所有文件
    select poll epoll Hello
    scanf() gets() fgets()使用注意事项 Hello
    gtk_init() Hello
    用C实现FFT算法 Hello
    时间相关函数 Hello
    gcc的编译属性和选项 Hello
  • 原文地址:https://www.cnblogs.com/candy99/p/5967339.html
Copyright © 2020-2023  润新知