1 条题解
-
0
自动搬运
来自洛谷,原作者为

gan_ge
天下有道,以道殉身。天下无道,以身殉道。搬运于
2025-08-24 23:09:48,当前版本为作者最后更新于2025-08-07 17:02:00,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
先看测试点 :不会在 时出现
command操作,此时若以时间 为横坐标,机器人在数轴上的位置 为横坐标绘出机器人的轨迹,易知其为形如 的一次函数图像。但当 时出现
command操作时,该轨迹又会变成一条折线,极为不美观,此时若把折线分成若干线段,则每条线段仍满足上面的性质,但有定义域的限制。因此考虑离线,将每个机器人的轨迹分为若干线段存储,线段总数为 ( 个机器人,每次操作会产生 个新的线段)。
现在题目转化为:
现有 条形如 的线段, 次询问,每次给定一个数 ,求与直线 相交的线段中,交点纵坐标最大为多少。
显然是李超线段树,但交点坐标均为整数,比模版P4097 【模板】李超线段树还是好写点的。
注意:
- 值可能很大,要开
long long; - ,故要用动态开点线段树。
附代码:
#include<bits/stdc++.h> using namespace std; #define ls tr[p].l #define rs tr[p].r typedef long long ll; typedef long double ld; const int N=1e5+10; struct line{ int k;ll b; }p[N<<2]; int cnt=0; ll f(int id,int x){ return labs(1ll*p[id].k*x+p[id].b); } struct tree{ int l,r,id; }tr[N<<5]; int tot=0,rt=0; void pushnow(int &p,int l,int r,int now){ if(!p) p=++tot; int &lst=tr[p].id,mid=(l+r)>>1; if(f(now,mid)>f(lst,mid)) swap(now,lst); if(f(now,l)>f(lst,l)) pushnow(ls,l,mid,now); if(f(now,r)>f(lst,r)) pushnow(rs,mid+1,r,now); } void update(int &p,int l,int r,int ql,int qr,int now){ if(!p) p=++tot; if(ql<=l&&r<=qr) return pushnow(p,l,r,now),void(); int mid=(l+r)>>1; if(ql<=mid) update(ls,l,mid,ql,qr,now); if(qr>mid) update(rs,mid+1,r,ql,qr,now); } ll query(int p,int l,int r,int pl){ if(!p) return 0; ll res=f(tr[p].id,pl); int mid=(l+r)>>1; if(pl<=mid) return max(res,query(ls,l,mid,pl)); else return max(res,query(rs,mid+1,r,pl)); } int n,m,mxt=0,a[N]; vector<pair<int,int> > ch[N]; vector<int> q; int main(){ ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); cin>>n>>m; for(int i=1;i<=n;i++){ cin>>a[i]; ch[i].push_back({0,0}); } int t,k,x; string s; for(int i=1;i<=m;i++){ cin>>t>>s; mxt=max(mxt,t); if(s[0]=='c'){ cin>>k>>x; if((*ch[k].rbegin()).first==t) ch[k].pop_back(); ch[k].push_back({t,x}); } else q.push_back(t); } for(int i=1;i<=n;i++){ if((*ch[i].rbegin()).first!=mxt) ch[i].push_back({mxt,0}); ll y=a[i]; for(int j=1;j<(int)ch[i].size();j++){ int l=ch[i][j-1].first,r=ch[i][j].first,k=ch[i][j-1].second; p[++cnt]={k,y-1ll*k*l}; y+=1ll*(r-l)*k; update(rt,0,mxt,l,r,cnt); } } for(auto i:q) cout<<query(1,0,mxt,i)<<'\n'; return 0; } - 值可能很大,要开
- 1
信息
- ID
- 11495
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者