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

seika27
1.048596%||秋风扫落叶||哦对了朋友们我已经退役了||R95853||SR6G5-R3XA搬运于
2025-08-24 23:12:52,当前版本为作者最后更新于2025-05-06 17:05:07,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
思路
我们考虑将垃圾按 排序,然后维护一个集合,使这个集合中的最大的横坐标之差不大于 。
这个集合的维护是简单的,从左往右扫,每次遇到一个新的垃圾就去集合末尾踢掉一些垃圾。由于每个垃圾最多只会被加进集合一次,踢出集合一次,所以复杂度十分的正确。
那么接下来考虑如何快速计算集合内的答案。
我们考虑记 表示我们能选择的矩形的靠下的那条边纵坐标为 时,能捞到的垃圾重量之和。
下一步考虑加入一个新的垃圾进入集合,会对哪些 产生影响。
这个很容易就能推出来,当加入了一个纵坐标为 的新垃圾,那么当你的矩形最下面一条边的纵坐标 满足 时,你就可以捞到这个垃圾。
发现这是一个十分简单的区间修改,搞个线段树,发现这个纵坐标有点大,搞个离散化。
code
#include <bits/stdc++.h> #define int long long using namespace std; int n,w,h; const int N=1e5+5; struct point { int x,y,w; int ly,hy; }a[N]; int b[N<<1]; int tot; inline bool operator<(point a,point b) { return a.x^b.x?a.x<b.x:a.y^b.y?a.y<b.y:a.w<b.w; } struct sgt { int lar[N<<2],add[N<<2]; #define lx (x<<1) #define rx (x<<1|1) #define mid (L+R>>1) inline void up(int x) { lar[x]=max(lar[lx],lar[rx]); return; } inline void tag(int x,int L,int R) { if(add[x]) { lar[lx]+=add[x]; lar[rx]+=add[x]; add[lx]+=add[x]; add[rx]+=add[x]; add[x]=0; } return; } void update(int x,int L,int R,int l,int r,int v) { if(l<=L&&R<=r){lar[x]+=v,add[x]+=v;return;} tag(x,L,R); if(l<=mid)update(lx,L,mid,l,r,v); if(r>mid)update(rx,mid+1,R,l,r,v); up(x); return; } }subaru; int ans; signed main() { ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr); cin>>n>>w>>h; for(int i=1;i<=n;++i)cin>>a[i].x>>a[i].y>>a[i].w,b[++tot]=a[i].y,b[++tot]=a[i].y-h+1; sort(a+1,a+1+n); sort(b+1,b+1+tot); tot=unique(b+1,b+1+tot)-b-1; for(int i=1;i<=n;++i)a[i].ly=lower_bound(b+1,b+1+tot,a[i].y-h+1)-b,a[i].hy=lower_bound(b+1,b+1+tot,a[i].y)-b; for(int i=1,j=1;i<=n;++i) { subaru.update(1,1,n,a[i].ly,a[i].hy,a[i].w); while(a[j].x+w-1<a[i].x)subaru.update(1,1,n,a[j].ly,a[j].hy,-a[j].w),++j; ans=max(ans,subaru.lar[1]); } cout<<ans; return 0; }
- 1
信息
- ID
- 11898
- 时间
- 5500ms
- 内存
- 1024MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者