题目:http://noi.openjudge.cn/ch0111/03/
以下面例子说明解题思路:
6 2 1 1 1 1 3 1 2 1
并记a[i]表示直线x=i-1与x=i之前的矩形面积,得a[1..6]={0,1,0,1,1,0},前缀和s[1..6]={0,1,1,2,2,2},那么问题可以这样处理:先二分找到满足左边矩形面积不小于右边矩形面积的第一个元素位置,这里是2——二分查找求下界。
因为s[2]=s[3],所以需要上滤到3。
注意数据类型,极端情形下,R=10^6,从而R^2=10^12,考虑前缀和,将超过int——所以用long long。
#include<cstdio>
#include<iostream>
using namespace std;
long long a[1000001],sa[1000001];/*int,失3分*/
int R,n;
int BSearch(int l,int r){
int mid;
while(l<r){/*lower_pound()二分求下界*/
mid=l+(r-l)/2;
if(2*sa[mid]>=sa[R])r=mid;
else l=mid+1;
}
return l;
}
int main(){
cin>>R>>n;
int L,T,W,H;
for(int i=0;i<n;i++){
cin>>L>>T>>W>>H;
for(int j=1;j<=W;j++) a[L+j]+=H;
}
for(int i=1;i<=R;i++)
sa[i]=sa[i-1]+a[i];/*前缀和*/
int t=BSearch(1,R);
/*上滤。使得大矩形在直线左边的的面积尽可能大*/
while(t<R && sa[t+1]==sa[t])t++;
cout<<t<<endl;
return 0;
}