【bzoj3938】【Robot】【线段树】

来源:互联网 发布:著名搞笑网络歌曲 编辑:程序博客网 时间:2024/06/13 23:03

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 longusing 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