自己想到的就是用线段树+扫描线了,看了别人的解题报告发现直接用二分就可以了
用二分的话注意一点,即mid如果恰处于两个窗器之间的部分也算满足条件了
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<math.h>
using namespace std;
const double eps=1e-4;
struct Cistern{
int b,h,w,d;
};
Cistern a[50005];
int k,n;
int main(){
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif // ONLINE_JUDGE
scanf("%d",&k);
int v;
while(k--){
scanf("%d",&n);
double s=0;
for(int i=0;i<n;i++){
scanf("%d%d%d%d",&a[i].b,&a[i].h,&a[i].w,&a[i].d);
s+=a[i].h*a[i].w*a[i].d;
}
scanf("%d",&v);
if(s+eps<v) {
printf("OVERFLOW\n");
continue;
}
double low=0,high=2000000,mid;
while(low<high-eps){
double s=v;
mid=(low+high)/2;
//printf("%.2f %.2f %.2f\n",low,mid,high);
for(int i=0;i<n;i++){
if(a[i].b+a[i].h<=mid+eps) {
s-=a[i].h*a[i].w*a[i].d;
}
else if(a[i].b<=mid+eps) {
s-=(mid-a[i].b)*a[i].w*a[i].d;
}
}
if(fabs(s)<eps) high=mid;//break;
else if(s>eps) low=mid;
else high=mid;
}
printf("%.2f\n",mid);
//printf("%.2f %.2f %.2f\n",low,mid,high);
}
}