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; }