题意:有三维的空间里有N个点(N<5000),要求用一个长方体LB*LW*LH去包围一些点,使得长方体内的点的权值和最小。
因为N只有5000,起先我们的方法是暴力去枚举两维,即按X排序,找出点彼此间距离不超过LB的点,然后将这些点按Y排序,在线段树中放进Y之间最大距离不超过LW的点。。但是这样死活过不了。。最后枚举一维,直接按X排序,然后就是poj 2482的做法了。。
#include <iostream> #include <cstdio> #include <cstring> #include <vector> #include <algorithm> using namespace std; #define LL(x) (x<<1) #define RR(x) (x<<1|1) #define MID(a,b) (a+((b-a)>>1)) const int N=5005; int n; int LB,LW,LH; struct REC { int x,y,z,w; REC(){} REC(int x,int y,int z,int w) : x(x),y(y),z(z),w(w) {} bool operator<(const REC &B)const { return x<B.x; } }; struct Line { int x,y1,y2,w; Line(){} Line(int x,int y1,int y2,int w) : x(x),y1(y1),y2(y2),w(w) {} bool operator<(const Line &B)const { return x<B.x||(x==B.x&&w>B.w); } }; vector<REC> rec; vector<Line> line; struct Segtree { int mx[N*4],delay[N*4]; void fun(int ind,int valu) { mx[ind]+=valu; delay[ind]+=valu; } void PushDown(int ind) { if(delay[ind]) { fun(LL(ind),delay[ind]); fun(RR(ind),delay[ind]); delay[ind]=0; } } void PushUp(int ind) { mx[ind]=max(mx[LL(ind)],mx[RR(ind)]); } void build(int lft,int rht,int ind) { mx[ind]=delay[ind]=0; if(lft!=rht) { int mid=MID(lft,rht); build(lft,mid,LL(ind)); build(mid+1,rht,RR(ind)); } } void updata(int st,int ed,int valu,int lft,int rht,int ind) { if(st<=lft&&rht<=ed) fun(ind,valu); else { PushDown(ind); int mid=MID(lft,rht); if(st<=mid) updata(st,ed,valu,lft,mid,LL(ind)); if(ed> mid) updata(st,ed,valu,mid+1,rht,RR(ind)); PushUp(ind); } } }seg; int calc(int st,int ed) { line.clear(); for(int i=st;i<=ed;i++) { int y=rec[i].y; int z=rec[i].z; int w=rec[i].w; line.push_back(Line(y,z,z+LH,w)); line.push_back(Line(y+LW,z,z+LH,-w)); } sort(line.begin(),line.end()); seg.build(0,N,1); int len=(int)line.size(),mx=0; for(int i=0;i<len;i++) { seg.updata(line[i].y1,line[i].y2,line[i].w,0,N,1); mx=max(mx,seg.mx[1]); } return mx; } int main() { // freopen("in.txt","r",stdin); while(scanf("%d",&n)!=EOF) { rec.clear(); line.clear(); for(int i=0;i<n;i++) { int a,b,c,d; scanf("%d%d%d%d",&a,&b,&c,&d); if(d>=0) continue; a+=1000; b+=1000; c+=1000; rec.push_back(REC(a,b,c,-d)); } scanf("%d%d%d",&LB,&LW,&LH); if(rec.size()==0) { puts("Error 404, mahou shoujo not found!"); continue; } n=(int)rec.size(); sort(rec.begin(),rec.end()); int ind1=0,ind2=0,mx=0; while(ind1<n) { while(ind2<n&&rec[ind2].x-rec[ind1].x<=LB) ind2++; mx=max(mx,calc(ind1,ind2-1)); if(ind2==n) break; while(ind1+1<n&&rec[ind1].x==rec[ind1+1].x) ind1++; ind1++; } printf("%d\n",-mx); } return 0; }
#include <iostream> #include <cstdio> #include <cstring> #include <vector> #include <map> #include <set> #include <algorithm> using namespace std; #define LL(x) (x<<1) #define RR(x) (x<<1|1) #define MID(a,b) (a+((b-a)>>1)) const int N=5005; struct REC { int x,y,z,w; REC(){} REC(int x,int y,int z,int w) : x(x),y(y),z(z),w(w) {} void print() { cout<<x<<" "<<y<<" "<<z<<" "<<w<<endl; } }; bool cmpX(const REC &A,const REC &B) { return A.x<B.x; } bool cmpY(const REC &A,const REC &B) { return A.y<B.y; } int n,LB,LW,LH,ans; vector<REC> rec; vector<REC> order; struct Segtree { int mx[N*4],delay[N*4]; void PushUp(int ind) { mx[ind]=max(mx[LL(ind)],mx[RR(ind)]); } void fun(int ind,int valu) { mx[ind]+=valu; delay[ind]+=valu; } void PushDown(int ind) { if(delay[ind]) { fun(LL(ind),delay[ind]); fun(RR(ind),delay[ind]); delay[ind]=0; } } void build(int lft,int rht,int ind) { mx[ind]=delay[ind]=0; if(lft!=rht) { int mid=MID(lft,rht); build(lft,mid,LL(ind)); build(mid+1,rht,RR(ind)); } } void updata(int st,int ed,int valu,int lft,int rht,int ind) { if(st<=lft&&rht<=ed) fun(ind,valu); else { PushDown(ind); int mid=MID(lft,rht); if(st<=mid) updata(st,ed,valu,lft,mid,LL(ind)); if(ed> mid) updata(st,ed,valu,mid+1,rht,RR(ind)); PushUp(ind); } } }seg; void fun(int st,int ed) { seg.build(0,N,1); order.clear(); for(int i=st;i<=ed;i++) order.push_back(rec[i]); sort(order.begin(),order.end(),cmpY); int len=(int)order.size(); int ind1=0,ind2=0; while(ind1<len) { int y1=order[ind1].y; int z1=order[ind1].z; int w1=order[ind1].w; while(ind2<len) { int y2=order[ind2].y; int z2=order[ind2].z; int w2=order[ind2].w; if(y2-y1<=LW) { seg.updata(z2,z2+LH,w2,0,N,1); ans=max(ans,seg.mx[1]); ind2++; } else break; } seg.updata(z1,z1+LH,-w1,0,N,1); ans=max(ans,seg.mx[1]); ind1++; } } int main() { //freopen("in.txt","r",stdin); while(scanf("%d",&n)!=EOF) { ans=0; rec.clear(); order.clear(); for(int i=0;i<n;i++) { int a,b,c,d; scanf("%d%d%d%d",&a,&b,&c,&d); if(d>=0) continue; a+=1000; b+=1000; c+=1000; rec.push_back(REC(a,b,c,-d)); } scanf("%d%d%d",&LB,&LW,&LH); if(rec.size()==0) { puts("Error 404, mahou shoujo not found!"); continue; } sort(rec.begin(),rec.end(),cmpX); int ind1=0,ind2=0; while(ind1<n) { while(ind2<n&&rec[ind2].x-rec[ind1].x<=LB) ind2++; fun(ind1,ind2); while(ind1+1<n&&rec[ind1].x==rec[ind1+1].x) ind1++; ind1++; } printf("%d\n",-ans); } return 0; }