题目链接:Disappearance
题意:每一个物品有
B,W,H,S
四种属性,问能否选出一个物品的集合,使得前三种属性的极值小于给定值,且
S
属性的和最小,如果答案不为负数,输出给定的字符串。
解法:注意到
一样了,线段树+扫描线即可。
#include <bits/stdc++.h>
using namespace std;
const int N = 1005;
struct Line{
int l,r,h,d;
}l[N<<1];
struct Node{
int l,r,v,tg;
}a[N<<3];
inline void PushUp(int i){
a[i].v=min(a[i<<1].v,a[i<<1|1].v);
}
void Build(int i,int l,int r){
a[i].l=l;
a[i].r=r;
a[i].v=a[i].tg=0;
if(l==r)
return ;
int mid=l+r>>1;
Build(i<<1,l,mid);
Build(i<<1|1,mid+1,r);
PushUp(i);
}
inline void PushDown(int i){
if(a[i].tg){
a[i<<1].v+=a[i].tg;
a[i<<1].tg+=a[i].tg;
a[i<<1|1].v+=a[i].tg;
a[i<<1|1].tg+=a[i].tg;
a[i].tg=0;
}
}
void Add(int i,int l,int r,int d){
if(l<=a[i].l&&a[i].r<=r){
a[i].v+=d;
a[i].tg+=d;
return ;
}
PushDown(i);
if(l<=a[i<<1].r)
Add(i<<1,l,r,d);
if(a[i<<1|1].l<=r)
Add(i<<1|1,l,r,d);
PushUp(i);
}
struct BWH{
int x,y,z,s;
}bwh[N];
set<int>Sx;
map<int,int>My;
int t[N<<1];
inline bool cmp(const Line& q,const Line& w){
if(q.h==w.h)
return q.d<w.d;
return q.h<w.h;
}
int main(){
int n,b,w,h;
while(scanf("%d",&n)==1){
Sx.clear();
My.clear();
for(int i=1;i<=n;i++){
scanf("%d %d %d %d",&bwh[i].x,&bwh[i].y,&bwh[i].z,&bwh[i].s);
bwh[i].y*=2;
bwh[i].z*=2;
Sx.insert(bwh[i].x);
}
scanf("%d %d %d",&b,&w,&h);
w*=2;
h*=2;
int ans=0;
for(set<int>::iterator it=Sx.begin();it!=Sx.end();it++){
int c=(*it),cnt=0,tp=0;
My.clear();
for(int i=1;i<=n;i++)
if(bwh[i].s<0&&c<=bwh[i].x&&bwh[i].x<=c+b){
// cout<<bwh[i].y<<' '<<w/2<<endl;
l[cnt].l=bwh[i].y-w/2;
l[cnt].r=bwh[i].y+w/2;
t[cnt]=l[cnt].l;
l[cnt].h=bwh[i].z-h/2;
l[cnt++].d=bwh[i].s;
l[cnt].l=bwh[i].y-w/2;
l[cnt].r=bwh[i].y+w/2;
t[cnt]=l[cnt].r;
l[cnt].h=bwh[i].z+h/2;
l[cnt++].d=-bwh[i].s;
}
sort(t,t+cnt);
int len=unique(t,t+cnt)-t;
for(int i=0;i<len;i++)
My[t[i]]=i+1;
sort(l,l+cnt,cmp);
if(len){
Build(1,1,len);
for(int i=0;i<cnt;i++){
tp=min(tp,a[1].v);
Add(1,My[l[i].l],My[l[i].r],l[i].d);
}
}
ans=min(ans,tp);
}
if(ans<0)
printf("%d\n",ans);
else
puts("Error 404, mahou shoujo not found!");
}
return 0;
}