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
-20 0 20 100
10 command 1 10
20 command 3 -10
30 query
40 command 1 -30
50 query
Sample Output
180
280
280
HINT
第一个命令执行时,各个机器人的位置为:−20,0,20,100。
第二个命令执行时,各个机器人的位置为:80,0,20,100。
第一个询问时,各个机器人的位置为:180,0,−80,100。
第三个命令执行时,各个机器人的位置为:280,0,−180,100。
对于所有的机器人满足 ∣ai∣≤10^9。
N,C<=10^5
Q<=5*10^5第二个询问时,各个机器人的位置为:−20,0,−280,100。
限制与约定
设 command 的个数为 C,query 的个数为 Q。(所以 C+Q=m)
对于所有的事件满足 0≤ti≤10^9,对于所有的 command 满足 ∣xi∣≤10^4。分析: 我们可以把时间建成线段树 首先把时间离散一下 在超哥线段树中插入线段即可 因为我们最后查询的是绝对值最大的位置 因此我们在线段树中要维护**最上方和最下方的线段** 标记永久化单点查询即可
tip
每个结点都设置一个覆盖标记,
如果从来没有线段覆盖过,在初次覆盖的时候直接看一下标记即可
查询的时候也可以通过判断标记防止答案错误
注意在判断交点在哪一个区间的时候,不要忘了线段树的区间是离散后的时间
if (x<=ti[mid])
啊啊啊啊啊。。。。写了一下午+一晚上
一开始没有想明白离散化
后来发现没有看见是绝对值最大
代码量超长180+
在bzoj上一直T
发现是在线段树中没有及时return:
if (r<l) return;
终于变成了WA
本来是想借鉴一下前辈的代码,最后只能找不同了。。。
在处理的时候,我们添加一个时刻0,方便计算直线的斜率和截距
插入线段时候,我们把每一个机器人按照操作顺序分成若干段分别插入
数据应该是保证时间是单调递增的
这道题虽然是自己想出来的,但是调了好久。。。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int INF=1e9;
const int N=600005;
struct node{
ll mxa,mxb,mna,mnb;
};
node T[N<<2];
int n,m,nn;
struct point{
int type;
ll x,y,tm;
};
point po[N];
ll ti[N],A[N],maxx,minn,nowk[N],nowb[N];
bool f1[N<<2],f2[N<<2];
void change_max(int bh,int l,int r,int L,int R,ll K,ll B)
{
if (r<l) return;
int mid=(l+r)>>1;
if (l>=L&&r<=R)
{
if (!f1[bh])
{
T[bh].mxa=K; T[bh].mxb=B; f1[bh]=1;
return;
}
ll z1=T[bh].mxa*ti[l]+T[bh].mxb; //原线段
ll z2=T[bh].mxa*ti[r]+T[bh].mxb;
ll z3=K*ti[l]+B;
ll z4=K*ti[r]+B;
if (z1>=z3&&z2>=z4) return;
if (z1<=z3&&z2<=z4)
{
T[bh].mxa=K; T[bh].mxb=B;
return;
}
double x=(double)(T[bh].mxb-B)/(K-T[bh].mxa);
if (x<=ti[mid]) //对比的是原时间
{
if (z1<z3) change_max(bh<<1,l,mid,L,R,K,B);
else {
change_max(bh<<1,l,mid,L,R,T[bh].mxa,T[bh].mxb);
T[bh].mxa=K; T[bh].mxb=B;
}
}
else
{
if (z1>z3) change_max((bh<<1)+1,mid+1,r,L,R,K,B);
else{
change_max((bh<<1)+1,mid+1,r,L,R,T[bh].mxa,T[bh].mxb);
T[bh].mxa=K; T[bh].mxb=B;
}
}
return;
}
if (L<=mid) change_max(bh<<1,l,mid,L,R,K,B);
if (R>mid) change_max((bh<<1)+1,mid+1,r,L,R,K,B);
}
void change_min(int bh,int l,int r,int L,int R,ll K,ll B)
{
if (r<l) return;
int mid=(l+r)>>1;
if (l>=L&&r<=R)
{
if (!f2[bh])
{
T[bh].mna=K; T[bh].mnb=B; f2[bh]=1;
return;
}
ll z1=T[bh].mna*ti[l]+T[bh].mnb; //原线段
ll z2=T[bh].mna*ti[r]+T[bh].mnb;
ll z3=K*ti[l]+B;
ll z4=K*ti[r]+B;
if (z1<=z3&&z2<=z4) return;
if (z1>=z3&&z2>=z4)
{
T[bh].mna=K; T[bh].mnb=B;
return;
}
double x=(double)(T[bh].mnb-B)/(K-T[bh].mna);
if (x<=ti[mid]) //对比的是原时间
{
if (z1>z3) change_min(bh<<1,l,mid,L,R,K,B);
else {
change_min(bh<<1,l,mid,L,R,T[bh].mna,T[bh].mnb);
T[bh].mna=K; T[bh].mnb=B;
}
}
else
{
if (z1<z3) change_min((bh<<1)+1,mid+1,r,L,R,K,B);
else{
change_min((bh<<1)+1,mid+1,r,L,R,T[bh].mna,T[bh].mnb);
T[bh].mna=K; T[bh].mnb=B;
}
}
return;
}
if (L<=mid) change_min(bh<<1,l,mid,L,R,K,B);
if (R>mid) change_min((bh<<1)+1,mid+1,r,L,R,K,B);
}
void ask(int bh,int l,int r,int pos)
{
if (r<l) return;
if (f1[bh]) maxx=max(maxx,T[bh].mxa*ti[pos]+T[bh].mxb); //一路上都要维护
if (f2[bh]) minn=min(minn,T[bh].mna*ti[pos]+T[bh].mnb);
if (l==r) return;
int mid=(l+r)>>1;
if (pos<=mid) ask(bh<<1,l,mid,pos);
else ask((bh<<1)+1,mid+1,r,pos);
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) scanf("%lld",&nowb[i]),nowk[i]=0,A[i]=0;
char s[20];
for (int i=1;i<=m;i++)
{
scanf("%lld",&po[i].tm); ti[i]=po[i].tm;
scanf("%s",s);
if (s[0]=='c')
{
po[i].type=1;
scanf("%lld%lld",&po[i].x,&po[i].y);
}
else po[i].type=2;
}
int num=m;
ti[++num]=0; //添加一个初试时刻0
sort(ti+1,ti+1+num); //离散化时间
nn=unique(ti+1,ti+1+num)-ti-1;
for (int i=1;i<=m;i++) if (po[i].type==1)
{
int x=po[i].x;
int lst=lower_bound(ti+1,ti+1+nn,A[x])-ti; //编号x上一次修改的时间
int now=lower_bound(ti+1,ti+1+nn,po[i].tm)-ti; //编号x这次修改的时间
change_max(1,1,nn,lst,now,nowk[x],nowb[x]);
change_min(1,1,nn,lst,now,nowk[x],nowb[x]);
nowb[x]=po[i].tm*(nowk[x]-po[i].y)+nowb[x];
nowk[x]=po[i].y; A[x]=po[i].tm;
}
for (int i=1;i<=n;i++)
{
int now=lower_bound(ti+1,ti+1+nn,A[i])-ti;
change_max(1,1,nn,now,nn,nowk[i],nowb[i]);
change_min(1,1,nn,now,nn,nowk[i],nowb[i]);
}
for (int i=1;i<=m;i++) if (po[i].type==2)
{
maxx=0; minn=0;
int now=lower_bound(ti+1,ti+1+nn,po[i].tm)-ti;
ask(1,1,nn,now);
printf("%lld\n",max(maxx,-minn));
}
return 0;
}