【bzoj3938】【Robot】【线段树】

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

题解:

          把时间当x轴,距离当y轴,那每次就相当于插入一条线段.

          然后就是线段树维护一次函数的经典问题了.

          因为是绝对值最大,所以要维护最大值和最小值

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#define N 100010
#define M 600010
#define inf 1000000000000000ll
#define LL long long
using namespace std;
int mx[M<<2],mn[M<<2],n,m,x,v,size,num,h[M];
LL ans,maxx,minn;
struct node{int k;LL b;}line[M<<2];
struct Q{int kind,t,x;}q[M];
struct L{int l,r,k,cnt;LL b;};
char ch[10];
vector<L>xu[N];
int read(){
  int x(0),f=1;char ch=getchar();
  while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
  while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
  return x*f;
}
LL cal(node t,int x){
  LL ans;
  //cout<<t.k<<' '<<t.b<<' '<<x<<endl;
  ans=(LL)t.k*x+t.b;    
  //cout<<ans<<endl;
  return ans;
}
void query(int k,int l,int r,int x){
  int mid=(l+r)>>1;//cout<<l<<' '<<r<<' '<<x<<' '<<mx[k]<<' '<<mn[k]<<endl;
  if (mx[k]) maxx=max(maxx,cal(line[mx[k]],x));
  if (mn[k]) minn=min(minn,cal(line[mn[k]],x));
  if (l==r) return;
  if (x<=h[mid]) query(k<<1,l,mid,x);
  else query(k<<1|1,mid+1,r,x);
}
void insmn(int k,int l,int r,int ll,int rr,int pos){
  int mid=(l+r)>>1;
  if (ll<=h[l]&&h[r]<=rr){
    if (!mn[k]){mn[k]=pos;return;}
    node l1=line[mn[k]],l2=line[pos];
    LL a1=cal(l1,h[l]),b1=cal(l1,h[r]);
    LL a2=cal(l2,h[l]),b2=cal(l2,h[r]);
    if (a1<=a2&&b1<=b2) return;
    if (a1>a2&&b1>b2){mn[k]=pos;return;}
    LL mid1=cal(l1,h[mid]),mid2=cal(l2,h[mid]);
    if (a1<=a2){
      if (mid1>=mid2){
        insmn(k<<1,l,mid,ll,rr,mn[k]);
        mn[k]=pos;
      }
      else insmn(k<<1|1,mid+1,r,ll,rr,pos);
    }
    else{
      if (mid1>=mid2){
        insmn(k<<1|1,mid+1,r,ll,rr,mn[k]);
        mn[k]=pos;
      }
      else insmn(k<<1,l,mid,ll,rr,pos);
    }
  }
  else{
    if (ll<=h[mid]) insmn(k<<1,l,mid,ll,rr,pos);
    if (h[mid]<rr) insmn(k<<1|1,mid+1,r,ll,rr,pos);
  } 
}
void insmx(int k,int l,int r,int ll,int rr,int pos){
  int mid=(l+r)>>1;
  if (ll<=h[l]&&h[r]<=rr){
    if (!mx[k]){mx[k]=pos;return;}
    node l1=line[mx[k]],l2=line[pos];
    LL a1=cal(l1,h[l]),b1=cal(l1,h[r]);
    LL a2=cal(l2,h[l]),b2=cal(l2,h[r]);
    if (a1>=a2&&b1>=b2) return;
    if (a1<a2&&b1<b2){mx[k]=pos;return;}
    LL mid1=cal(l1,h[mid]),mid2=cal(l2,h[mid]);
    if (a1<=a2){
      if (mid1<=mid2){
        insmx(k<<1|1,mid+1,r,ll,rr,mx[k]);
        mx[k]=pos;
      }
      else insmx(k<<1,l,mid,ll,rr,pos);
    }
    else{
      if (mid1<=mid2){
        insmx(k<<1,l,mid,ll,rr,mx[k]);
        mx[k]=pos;
      }
      else insmx(k<<1|1,mid+1,r,ll,rr,pos);
    }
  }
  else{
    if (ll<=h[mid]) insmx(k<<1,l,mid,ll,rr,pos);
    if (h[mid]<rr) insmx(k<<1|1,mid+1,r,ll,rr,pos);
  }
}
LL myabs(LL x){
  if (x<0) return -x;
  else return x;
}
int main(){
  //freopen("a.in","r",stdin);
  //freopen("a.out","w",stdout);
  n=read();m=read();h[1]=0;
  for (int i=1;i<=n;i++){
    x=read();
    xu[i].push_back(L{0,0,0,++num,(LL)x});
  } 
  for (int i=1;i<=m;i++){
    q[i].t=h[i+1]=read();scanf("%s",ch);
    if (ch[0]=='c'){
      q[i].kind=1;
      x=read();v=read();
      int temp=xu[x].size()-1;
      xu[x][temp].r=q[i].t;
      L now;
      now.l=q[i].t;now.r=0;now.k=v;now.cnt=++num;
      now.b=cal(node{xu[x][temp].k,xu[x][temp].b},q[i].t)-(LL)v*q[i].t; 
      xu[x].push_back(now);
    }
  }
  for (int i=1;i<=n;i++)
    if (xu[i][xu[i].size()-1].r==0) xu[i][xu[i].size()-1].r=q[m].t;
  size=unique(h+1,h+m+2)-h-1;
  for (int i=1;i<=n;i++)
    for (int j=0;j<=xu[i].size()-1;j++){
      L now=xu[i][j];
      line[now.cnt]=node{now.k,now.b};
      //cout<<now.k<<' '<<now.b<<' '<<now.l<<' '<<now.r<<endl;
      insmn(1,1,size,now.l,now.r,now.cnt);
      insmx(1,1,size,now.l,now.r,now.cnt);
    }
 // cout<<"-----"<<endl;
  for (int i=1;i<=m;i++)
    if (!q[i].kind){
      maxx=-inf;minn=inf;
      query(1,1,size,q[i].t);
      //cout<<maxx<<' '<<minn<<endl;
      ans=max(myabs(maxx),myabs(minn));
      printf("%lld\n",ans);
    }
} 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值