[bzoj3938] [Uoj #88] Robot

Posted lindalee

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[bzoj3938] [Uoj #88] Robot相关的知识,希望对你有一定的参考价值。

Description

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

Input

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

Output

对于每个 \(query\) 询问,输出一行,包含一个整数表示正确的答案。

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 \leq ti \leq 10^9\),对于所有的 \(command\) 满足 \(∣x_i∣ \leq 10^4\)

对于所有的机器人满足 \(∣a_i∣ \leq 10^9\)

\(N,C \leq 10^5\)

\(Q \leq 5 \times 10^5\)


想法

稍稍转化一下,以时间为 \(x\) 轴,位置为 \(y\) 轴,就是一道经典的李超线段树题。
就是处理细节比较多,要离线处理插入的线段,要对时间离散化。


代码

明明是道水题,我却调了2个多小时,因为一些奇奇怪怪的原因(如 \(double\)\(longlong\) 啊,对时间离散化还是动态开点啊,线段的端点问题啊。。。)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
 
using namespace std;
 
int read()
    int x=0,f=1;
    char ch=getchar();
    while(!isdigit(ch) && ch!='-') ch=getchar();
    if(ch=='-') f=-1,ch=getchar();
    while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
    return x*f;

 
const int N = 600005;
typedef double db;
typedef long long ll;
 
struct seg
    int x0,x1;
    ll k,b;
    seg()  x0=x1=0; k=b=0.0; 
    seg(int _x0,int _x1,ll _k,ll _b)  x0=_x0; x1=_x1; k=_k; b=_b; 
d[N];
int tot;
int ask[N],num;
 
int n;
ll K[N],B[N];
int st[N];
 
int rk[N*2],rn;
struct node
    node *ch[2];
    int mx,mn;
    node()  mx=mn=0; ch[0]=ch[1]=NULL; 
pool[N*4],*root;
int cnt;
void build(node *p,int l,int r)
    if(l==r) return;
    int mid=(l+r)>>1;
    build(p->ch[0]=&pool[++cnt],l,mid);
    build(p->ch[1]=&pool[++cnt],mid+1,r);

inline ll cal(int x,int c)  return d[x].k*rk[c]+d[x].b; 
bool better_mn(int x,int y,int c)  
    if(!x) return false;
    if(!y) return true;
    return cal(x,c)<cal(y,c);

bool better_mx(int x,int y,int c)  
    if(!x) return false;
    if(!y) return true;
    return cal(x,c)>cal(y,c);

void insert_mx(node *p,int l,int r,int L,int R,int c)
    if(l==L && r==R)
        int mid=(l+r)>>1;
        if(better_mx(c,p->mx,mid)) swap(p->mx,c);
        int tl=better_mx(p->mx,c,l),tr=better_mx(p->mx,c,r);
        if(c==0 || l==r || (tl && tr)) return;
        if(tl) insert_mx(p->ch[1],mid+1,r,mid+1,r,c);
        else insert_mx(p->ch[0],l,mid,l,mid,c);
        return;
    
    int mid=(l+r)>>1;
    if(R<=mid) insert_mx(p->ch[0],l,mid,L,R,c);
    else if(L>mid) insert_mx(p->ch[1],mid+1,r,L,R,c);
    else
        insert_mx(p->ch[0],l,mid,L,mid,c);
        insert_mx(p->ch[1],mid+1,r,mid+1,R,c);
    
 
void insert_mn(node *p,int l,int r,int L,int R,int c)
    if(l==L && r==R)
        int mid=(l+r)>>1;
        if(better_mn(c,p->mn,mid)) swap(p->mn,c);
        int tl=better_mn(p->mn,c,l),tr=better_mn(p->mn,c,r);
        if(c==0 || l==r || (tl && tr)) return;
        if(tl) insert_mn(p->ch[1],mid+1,r,mid+1,r,c);
        else insert_mn(p->ch[0],l,mid,l,mid,c);
        return;
    
    int mid=(l+r)>>1;
    if(R<=mid) insert_mn(p->ch[0],l,mid,L,R,c);
    else if(L>mid) insert_mn(p->ch[1],mid+1,r,L,R,c);
    else
        insert_mn(p->ch[0],l,mid,L,mid,c);
        insert_mn(p->ch[1],mid+1,r,mid+1,R,c);
    
 
int Mx,Mn;
void query(node *p,int l,int r,int c)
    Mx = better_mx(p->mx,Mx,c) ? p->mx : Mx ;
    Mn = better_mn(p->mn,Mn,c) ? p->mn : Mn ;
    if(l==r) return;
    int mid=(l+r)>>1;
    if(c<=mid) query(p->ch[0],l,mid,c);
    else query(p->ch[1],mid+1,r,c);

 
int main()

    int m,t,id,x;
    char s[10];
    n=read();  m=read();
    for(int i=1;i<=n;i++)
        K[i]=0,B[i]=read(),st[i]=1;
    while(m--)
        t=read()+1;
        rk[++rn]=t;
        scanf("%s",s);
        if(s[0]=='c')
            id=read(); x=read();
            d[++tot]=seg(st[id],t,K[id],B[id]);
            st[id]=t;
            B[id]=K[id]*t+B[id]-1ll*x*t;
            K[id]=x;
        
        else ask[num++]=t;
    
    for(int i=1;i<=n;i++) d[++tot]=seg(st[i],t,K[i],B[i]);
    rk[++rn]=1;
     
    sort(rk+1,rk+1+rn);
    rn=unique(rk+1,rk+1+rn)-rk-1;
    build(root=&pool[++cnt],1,rn);
    for(int i=1;i<=tot;i++)
        if(d[i].x0==d[i].x1 && t!=1) continue;
        d[i].x0=lower_bound(rk+1,rk+1+rn,d[i].x0)-rk;
        d[i].x1=lower_bound(rk+1,rk+1+rn,d[i].x1)-rk;
        insert_mx(root,1,rn,d[i].x0,d[i].x1,i);
        insert_mn(root,1,rn,d[i].x0,d[i].x1,i);
    
    for(int i=0;i<num;i++)
        Mx=Mn=0;
        ask[i]=lower_bound(rk+1,rk+1+rn,ask[i])-rk;
        query(root,1,rn,ask[i]);
        printf("%lld\n",max(abs(cal(Mx,ask[i])),abs(cal(Mn,ask[i]))));
    
     
    return 0;
 

以上是关于[bzoj3938] [Uoj #88] Robot的主要内容,如果未能解决你的问题,请参考以下文章

bzoj3938 Robot

BZOJ 3938 Robot

UOJ #88. 集训队互测2015Robot 李超线段树

UOJ #88. 集训队互测2015Robot 李超线段树

BZOJ4942 & UOJ314:[NOI2017]整数——题解

[BZOJ3052][UOJ#58][WC2013]糖果公园