呜呜呜 这题弄了我好久
有一点很重要的是 你要看出一个点按照曼哈顿距离刚好就是围出来一个正方形 与坐标轴成45°
我们要让他与坐标轴平行 方便我们搞
然后就要把它“旋转一下” 然而我并不会QAQ 看了别人的之后大概知道 坐标变成 x+y,x-y 纵坐标避免负值都加上10^6
至于为什么 可以自行百度旋转坐标系
有个大神告诉我 你会发现正方形里一条边上的点 要弄成与坐标轴平行 所以x或者y是相等 接着同一条线的增幅是一样的 x都递增或减 y都递增或减 这样一加或者一减 就能达到x或y相等啦~(%%%%%hyc+部分自己脑补QAQ)
不懂的自己画一下就好啦,同时就顺便得到k变成2k 继续求曼哈顿距离~\(≧▽≦)/~
然后按其中一个排序一下 线段树搞一下就好了
本来愚蠢的我都不想写出来了
不过代码排18那么6 还是贴出来顺便写个题解蹭访问量(真的挺短挺好看 而且挺快~)
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> using namespace std; const int N=100005,M=1e6+1,inf=1e9; inline 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; } struct node{int x,y,c;}a[N]; int Cmp(node x1,node x2){return x1.y<x2.y;} int lazy[M<<3],mx[M<<3]; void pushdown(int x) { int lc=x<<1,rc=lc|1; if(lazy[x]!=0) { int lz=lazy[x]; lazy[x]=0; lazy[lc]+=lz,lazy[rc]+=lz; mx[lc]+=lz,mx[rc]+=lz; } } void change(int x,int l,int r,int ql,int qr,int u) { if(l!=r)pushdown(x); if(l==ql && r==qr){ lazy[x]+=u,mx[x]+=u; return; } int lc=x<<1,rc=lc|1,mid=(l+r)>>1; if(ql>mid)change(rc,mid+1,r,ql,qr,u); else if(qr<=mid)change(lc,l,mid,ql,qr,u); else { change(lc,l,mid,ql,mid,u); change(rc,mid+1,r,mid+1,qr,u); } mx[x]=max(mx[lc],mx[rc]); } int main() { int n=read(),k=read(),i,x,y,Max,Min; k<<=1; Max=1,Min=inf; for(i=1;i<=n;i++) { a[i].c=read(),x=read(),y=read(); a[i].x=x+y,a[i].y=x-y+M; Max=max(a[i].x,Max),Min=min(a[i].x,Min); } sort(a+1,a+1+n,Cmp); int l=0,r=0,ans=0; while(l<=n) { int ly=a[l].y; while(a[l].y==ly && l<=n) { if(l!=0)change(1,Min,Max,a[l].x,min(a[l].x+k,Max),-a[l].c); l++; } while(a[r+1].y-a[l].y<=k && r<n) { r++; change(1,Min,Max,a[r].x,min(a[r].x+k,Max),a[r].c); } ans=max(ans,mx[1]); } printf("%d\n",ans); return 0; }