• bzoj3938 Robot


    3938: Robot

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 336  Solved: 112
    [Submit][Status][Discuss]

    Description

    小q有n只机器人,一开始他把机器人放在了一条数轴上,第i只机器人在ai的位置上静止,而自己站在原点。在这
    之后小q会执行一些操作,他想要命令一个机器人向左或者向右移动x格。但是机器人似乎听不清小q的命令,事实
    上它们会以每秒x格的速度匀速移动。看着自己的机器人越走越远,小q很着急,他想知道当前离他(原点)最远的
    机器人有多远。具体的操作以及询问见输入格式。注意,不同的机器人之间互不影响,即不用考虑两个机器人撞在
    了一起的情况。
     
     

    Input

    共有m个事件,输入将会按事件的时间顺序给出。第一行两个正整数n,m。接下来一行n个整数,第i个数是ai,表示
    第i个机器人初始的位置(初始移动速度为0)。接下来m行,每行行首是一个非负整数ti,表示该事件点发生的时
    刻(以秒为单位)。第二个是一个字符串S,代表操作的种类。数字与字符串之间用一个空格隔开。接下来的输入
    按S的种类分类。若S是“command”(不带引号),则接下来两个整数ki,xi,表示小q对第ki个机器人执行了操作
    ,该机器人的速度将会被重置,变为向数轴正方向每秒移动xi格(若xi为负数就相当于向数轴负方向每秒移动∣xi
    ∣格)。保证1≤ki≤n。若S是“query”(不带引号),则你需要输出当前离原点最远的机器人有多远。保证t1≤
    t2≤t2≤...≤tm。(注:若同一时间发生多次操作,则按读入顺序依次执行)
     

    Output

    对于每个query询问,输出一行,包含一个整数表示正确的答案。C/C++输入输出longlong时请用%lld。由于本题数
    据量较大,建议不要使用cin/cout进行输入输出。
     

    Sample Input

    4 5
    -20 0 20 100
    10 command 1 10
    20 command 3 -10
    30 query
    40 command 1 -30
    50 query

    Sample Output

    180
    280

    HINT

    第一个命令执行时,各个机器人的位置为:−20,0,20,100。

    第二个命令执行时,各个机器人的位置为:80,0,20,100。

    第一个询问时,各个机器人的位置为:180,0,−80,100。

    第三个命令执行时,各个机器人的位置为:280,0,−180,100。

    第二个询问时,各个机器人的位置为:−20,0,−280,100。

    限制与约定

    设 command 的个数为 C,query 的个数为 Q。(所以 C+Q=m)

    对于所有的事件满足 0≤ti≤10^9,对于所有的 command 满足 ∣xi∣≤10^4。

    对于所有的机器人满足 ∣ai∣≤10^9。

    N,C<=10^5

    Q<=5*10^5

    Source

    分析:这道题和bzoj1568差不多,将t看做横坐标,相对于原点的距离看做纵坐标,最后求最大值和最小值,取各自绝对值的最大值,无非就是把直线改成了一条条的折线段.折线段的处理比较麻烦,比较考验细节处理能力.转化完后做法就基本上是一样的了.
              一些细节地方在代码中有注释
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    typedef long long ll;
    
    const ll maxn = 600010;
    
    ll n,m;
    ll Tim[maxn],v[maxn],d[maxn],cnt,Time[maxn],ans1,ans2;
    bool vis1[maxn << 2],vis2[maxn << 2];
    
    struct node
    {
        ll Time,V;
        ll opt,pos;
    } a[maxn];
    
    struct node2
    {
        ll k,b;
        ll id;
    } e1[maxn << 2],e2[maxn << 2];
    
    double jiao(node2 a,node2 b)
    {
        return (double)(a.b - b.b) / (b.k - a.k);
    }
    
    bool cmp(node2 a,node2 b,ll pos)
    {
        return a.k * pos + a.b < b.k * pos + b.b;
    }
    
    void update1(int o,int l,int r,int x,int y,node2 a)
    {
        int mid = (l + r) >> 1;
        if (x <= l && r <= y)
        {
            if (!vis1[o])
            {
                vis1[o] = 1;
                e1[o] = a;
            }
            else
            {
                ll l1 = a.b + a.k * Tim[l],l2 = a.b + a.k * Tim[r];
                ll r1 = e1[o].b + e1[o].k * Tim[l],r2 = e1[o].b + e1[o].k * Tim[r];
                if (l1 <= r1 && l2 <= r2)
                    return;
                if (l1 >= r1 && l2 >= r2)
                    e1[o] = a;
                else
                {
                    double X = jiao(a,e1[o]);
                    if (l1 >= r1)
                    {
                        if (X <= Tim[mid])
                            update1(o * 2,l,mid,x,y,a);
                        else
                            update1(o * 2 + 1,mid + 1,r,x,y,e1[o]),e1[o] = a;
                    }
                    else
                    {
                        if (X > Tim[mid])
                            update1(o * 2 + 1,mid + 1,r,x,y,a);
                        else
                            update1(o * 2,l,mid,x,y,e1[o]),e1[o] = a;
                    }
                }
            }
            return;
        }
        if (x <= mid)
            update1(o * 2,l,mid,x,y,a);
        if (y > mid)
            update1(o * 2 + 1,mid + 1,r,x,y,a);
    }
    
    void update2(int o,int l,int r,int x,int y,node2 a)
    {
        int mid = (l + r) >> 1;
        if (x <= l && r <= y)
        {
            if (!vis2[o])
            {
                vis2[o] = 1;
                e2[o] = a;
            }
            else
            {
                ll l1 = a.b + a.k * Tim[l],l2 = a.b + a.k * Tim[r];
                ll r1 = e2[o].b + e2[o].k * Tim[l],r2 = e2[o].b + e2[o].k * Tim[r];
                if (l1 >= r1 && l2 >= r2)
                    return;
                if (l1 <= r1 && l2 <= r2)
                    e2[o] = a;
                else
                {
                    double X = jiao(a,e2[o]);
                    if (l1 <= r1)
                    {
                        if (X <= Tim[mid])
                            update2(o * 2,l,mid,x,y,a);
                        else
                            update2(o * 2 + 1,mid + 1,r,x,y,e2[o]),e2[o] = a;
                    }
                    else
                    {
                        if (X > Tim[mid])
                            update2(o * 2 + 1,mid + 1,r,x,y,a);
                        else
                            update2(o * 2,l,mid,x,y,e2[o]),e2[o] = a;
                    }
                }
            }
            return;
        }
        if (x <= mid)
            update2(o * 2,l,mid,x,y,a);
        if (y > mid)
            update2(o * 2 + 1,mid + 1,r,x,y,a);
    }
    
    node2 query1(ll o,ll l,ll r,ll pos)
    {
        if (l == r)
            return e1[o];
        ll mid = (l + r) >> 1;
        node2 temp;
        if (pos <= mid)
            temp = query1(o * 2,l,mid,pos);
        else
            temp = query1(o * 2 + 1,mid + 1,r,pos);
        if (cmp(temp,e1[o],Tim[pos]))
            return e1[o];
        else
            return temp;
    }
    
    node2 query2(ll o,ll l,ll r,ll pos)
    {
        if (l == r)
            return e2[o];
        ll mid = (l + r) >> 1;
        node2 temp;
        if (pos <= mid)
            temp = query2(o * 2,l,mid,pos);
        else
            temp = query2(o * 2 + 1,mid + 1,r,pos);
        if (cmp(temp,e2[o],Tim[pos]))
            return temp;
        else
            return e2[o];
    }
    
    int main()
    {
        scanf("%lld%lld",&n,&m);
        for (ll i = 1; i <= n; i++)
            scanf("%lld",&d[i]);
        for (ll i = 1; i <= m; i++)
        {
            scanf("%lld",&Tim[i]);
            a[i].Time = Tim[i];
            char ch[10];
            scanf("%s",ch);
            if (ch[0] == 'c')
            {
                a[i].opt = 1;
                scanf("%lld%lld",&a[i].pos,&a[i].V);
            }
            else
                a[i].opt = 0;
        }
        cnt = m + 1;
        Tim[cnt] = 0;  //为了插入初始线段,加一个Tim = 0
        sort(Tim + 1,Tim + 1 + cnt);
        cnt = unique(Tim + 1,Tim + 1 + cnt) - Tim - 1; //去重离散化
        for (ll i = 1; i <= m; i++)
            if (a[i].opt == 1)
            {
                ll pos = a[i].pos;
                ll l = lower_bound(Tim + 1,Tim + 1 + cnt,Time[pos]) - Tim;
                ll r = lower_bound(Tim + 1,Tim + 1 + cnt,a[i].Time) - Tim;
                node2 temp;
                temp.k = v[pos];  //线段的斜率和截距
                temp.b = d[pos];
                update1(1,1,cnt,l,r,temp);
                update2(1,1,cnt,l,r,temp);
                d[pos] += a[i].Time * (v[pos] - a[i].V);  //新线段的截距.至于怎么求的,利用两条直线的交点列方程.a[i].Time就是交点横坐标
                v[pos] = a[i].V;  //v是记录上一次的斜率
                Time[pos] = a[i].Time;  //记录上一次这个机器人更改的时间
            }
        for (ll i = 1; i <= n; i++)
        {
            ll l = lower_bound(Tim + 1,Tim + 1 + cnt,Time[i]) - Tim;
            node2 temp;
            temp.k = v[i];
            temp.b = d[i];
            update1(1,1,cnt,l,cnt,temp);   //最后一条线段变成一条射线,延伸到右端点
            update2(1,1,cnt,l,cnt,temp);
        }
        for (ll i = 1; i <= m; i++)
            if (a[i].opt == 0)
            {
                ll l = lower_bound(Tim + 1,Tim + 1 + cnt,a[i].Time) - Tim;
                node2 temp1 = query1(1,1,cnt,l);
                node2 temp2 = query2(1,1,cnt,l);
                ll ans1 = temp1.k * Tim[l] + temp1.b;
                ll ans2 = temp2.k * Tim[l] + temp2.b;
                printf("%lld
    ",max(ans1,-ans2));
            }
    
        return 0;
    }
  • 相关阅读:
    215. Kth Largest Element in an Array
    B:魔兽世界之一:备战
    218. The Skyline Problem
    编程作业: 编程作业—类和对象
    239. Sliding Window Maximum
    313. Super Ugly Number
    hdu3068 manacher模板题
    fzu1901 kmp
    hdu2609 最小表示法
    hdu3374 kmp+最小表示法
  • 原文地址:https://www.cnblogs.com/zbtrs/p/8434760.html
Copyright © 2020-2023  润新知