呜呜呜 这题弄了我好久
有一点很重要的是 你要看出一个点按照曼哈顿距离刚好就是围出来一个正方形 与坐标轴成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;
}