题目大意
YYHS的校园可以抽象成一个无限二维平面,校园里分布着N个教室(编号为1..N),第i个教室的坐标为(x[i], y[i]),里面有w[i]个学生。新食堂的饭菜十分美味,然而同学们都比较懒。当且仅当新食堂的位置和第i个教室的位置的曼哈顿距离小于等于L,第i个教室里的学生会去新食堂吃饭。有博爱之心的NiroBC希望有尽量多的学生去新食堂吃饭,那么这个问题就交给你了!
解题思路
通过观察可以发现,有一些正方形,求一个点是包含它的正方形的价值和最大。首先以直线y=x为横轴,y=-x为纵轴建立平面直角坐标系,接着就可以用扫描线做,把一个正方形拆成添加和删除两个操作,用线段树维护最大值,修改区间加减。
code
using namespace std;
int const maxn=1e5;
int n,l,c[maxn*2+10],mx[maxn*8+10],tag[maxn*8+10];
LD b[maxn*2+10];
bool cmp(LD x,LD y){
return x+1e-10<y;
}
struct rec{
LD x,ly,ry;int op;
};
rec a[maxn*2+10];
bool cmp2(rec x,rec y){
return (x.x+1e-10<y.x)||((x.x<1e-10+y.x)&&(x.x+1e-10>y.x)&&(x.op>y.op));
}
void retag(int pos){
tag[pos*2]+=tag[pos];tag[pos*2+1]+=tag[pos];
mx[pos*2]+=tag[pos];mx[pos*2+1]+=tag[pos];
tag[pos]=0;
}
int qury(int pos,int l,int r,int ll,int rr){
int mid=(l+r)/2;
if(l!=r)retag(pos);
if((l==ll)&&(r==rr))return mx[pos];
else if(rr<=mid)return qury(pos*2,l,mid,ll,rr);
else if(mid<ll)return qury(pos*2+1,mid+1,r,ll,rr);
else return max(qury(pos*2,l,mid,ll,mid),qury(pos*2+1,mid+1,r,mid+1,rr));
}
void add(int pos,int l,int r,int ll,int rr,int val){
int mid=(l+r)/2;
if(l!=r)retag(pos);
if((l==ll)&&(r==rr)){
tag[pos]=val;
mx[pos]+=val;
return;
}else if(rr<=mid)add(pos*2,l,mid,ll,rr,val);
else if(mid<ll)add(pos*2+1,mid+1,r,ll,rr,val);
else{add(pos*2,l,mid,ll,mid,val);add(pos*2+1,mid+1,r,mid+1,rr,val);}
mx[pos]=max(mx[pos*2],mx[pos*2+1]);
}
int main(){
freopen("value.in","r",stdin);
freopen("value.out","w",stdout);
scanf("%d%d",&n,&l);
LD sqrt2=sqrt(2),R=l/sqrt2;
int cnt=0,cnt2=0;
fo(i,1,n){
int x,y,w;scanf("%d%d%d",&x,&y,&w);
LD xx=sqrt2*x+((y>x)?(y-x)/sqrt2:-(x-y)/sqrt2),
yy=((y>x)?(y-x)/sqrt2:-(x-y)/sqrt2);
a[++cnt].x=xx-R;a[cnt].ly=yy-R;a[cnt].ry=yy+R;a[cnt].op=w;
a[++cnt].x=xx+R;a[cnt].ly=yy-R;a[cnt].ry=yy+R;a[cnt].op=-w;
b[++cnt2]=yy-R;b[++cnt2]=yy+R;
}
sort(b+1,b+cnt2+1,cmp);
c[1]=1;fo(i,2,cnt2)c[i]=c[i-1]+(b[i-1]+1e-10<b[i]);
fo(i,1,cnt){
int l=1,r=cnt2;
for(;l!=r;){
int mid=(l+r)/2;
if(b[mid]+1e-10<a[i].ly)l=mid+1;
else r=mid;
}
a[i].ly=c[l];
l=1,r=cnt2;
for(;l!=r;){
int mid=(l+r)/2;
if(b[mid]+1e-10<a[i].ry)l=mid+1;
else r=mid;
}
a[i].ry=c[l];
}
sort(a+1,a+cnt+1,cmp2);
int ans=0;
fo(i,1,cnt){
if(a[i].op<0)ans=max(ans,qury(1,1,c[cnt2],a[i].ly,a[i].ry));
add(1,1,c[cnt2],a[i].ly,a[i].ry,a[i].op);
}
printf("%d",ans);
return 0;
}