BZOJ 1218: [HNOI2003]激光炸弹
Description
一个长度为R的正方形能圈住的最大点权。
Solution
扫描线.
可以将一个点转化成矩形,让覆盖它的矩形左上角在这个范围内时可以覆盖这个点。
然后就变成了若干个矩形求一个点的最大点权了,然后扫描线搞一搞...
Code
/**************************************************************
Problem: 1218
User: BeiYu
Language: C++
Result: Accepted
Time:152 ms
Memory:9144 kb
****************************************************************/
#include <bits/stdc++.h>
using namespace std;
#define mpr make_pair
typedef pair<int,int> pr;
const int N = 100500;
const int M = 5050;
inline int in(int x=0,char s=getchar(),int v=1) { while(s>'9'||s<'0')v=s=='-'?-1:v,s=getchar();
while(s>='0'&&s<='9')x=x*10+s-'0',s=getchar();return x*v; }
int n,r,cp,ans;
int xx[N],yy[N];
struct S { int x,y1,y2,w,f; }t[N<<1];
int cmpx(const S &a,const S &b) { return a.x==b.x?a.f>b.f:a.x<b.x; }
namespace Seg {
int mx[N<<2],tg[N<<2];
#define lc (o<<1)
#define rc (o<<1|1)
#define mid ((l+r)>>1)
void T(int o,int v) { tg[o]+=v,mx[o]+=v; }
void Push(int o,int l,int r) {
if(l==r) return;
if(tg[o]) T(lc,tg[o]),T(rc,tg[o]),tg[o]=0;
}
void Update(int o) { mx[o]=max(mx[lc],mx[rc]); }
void Add(int o,int l,int r,int L,int R,int v) {
Push(o,l,r);
if(L<=l && r<=R) { T(o,v);return; }
if(L<=mid) Add(lc,l,mid,L,R,v);
if(R>mid) Add(rc,mid+1,r,L,R,v);
Update(o);
}
int Qur(int o,int l,int r,int L,int R) {
Push(o,l,r);
if(L<=l && r<=R) return mx[o];
int res=0;
if(L<=mid) res=max(res,Qur(lc,l,mid,L,R));
if(R>mid) res=max(res,Qur(rc,mid+1,r,L,R));
return res;
}
}
int main() {
n=in(),r=in();
if(r<=0) return puts("0"),0;
for(int i=1;i<=n;i++) {
int x=in()+1,y=in()+1,z=in();
t[++cp]=(S) { x+1,y+1,y+r,z,1 };
t[++cp]=(S) { x+r,y+1,y+r,z,-1 };
}
sort(t,t+cp+1,cmpx);
for(int i=1,j,k;i<=cp;i=j+1) {
int x=t[i].x;
for(j=i;j+1<=cp && x==t[j+1].x;j++);
for(k=i;k<=j && t[k].f>0;k++)
Seg::Add(1,1,M,t[k].y1,t[k].y2,t[k].w);
ans=max(ans,Seg::Qur(1,1,M,1,M));
for(;k<=j;k++) Seg::Add(1,1,M,t[k].y1,t[k].y2,-t[k].w);
}
printf("%d\n",ans);
return 0;
}

浙公网安备 33010602011771号