看了大牛的代码才明白正确的解法是怎样的。一开始想的是只枚举快要到一半的那一部分,就是这个“快要”的判断要了我半条命,WA了N次。大牛的想法很犀利。
总结:对于这种问题,最好就是直接枚举所有情况,再在其他地方做优化保证不超时。
详细注释代码:
<span style="font-size:14px;">#include<stdio.h>
#include<string.h>
#include<math.h>
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
typedef long long lld;
lld mark[1000010];
int main()
{
int cas;
scanf("%d",&cas);
for(int cc=1;cc<=cas;cc++)
{
lld r;
scanf("%lld",&r);
lld total=0;
int n;
scanf("%d",&n);
memset(mark,0,sizeof(mark));
for(int i=0;i<n;i++)
{
lld l,t,w,h;
scanf("%lld %lld %lld %lld",&l,&t,&w,&h);
mark[l]+=h; //对于[l,l+w]这一段区间,从l开始享有高 为 h 的高,从l+w开始不享有
mark[l+w]-=h; //所以mark[l+w] 要-=h,mark[l]是+=h; //这样有效的解决了重叠的问题。
total+=h*w;
}
lld mls=r*r+1; //卫青的面积,一开始全分给他
lld mrs=0; //霍去病的面积,一开始为0;
lld ls,rs; //用来维护他们两的面积
ls=0;
rs=total;
lld hand=0;
lld ans=0;
for(int i=1;i<=r;i++)
{
hand+=mark[i-1]; //当前扫描的总面积
ls+=hand; //卫青的面积
rs-=hand; //霍去病的面积=总面积-卫青的面积
if(ls < rs) //如果卫青的面积 < 霍去病的面积,则不能更新
continue;
if(ls-rs <= mls-mrs) //如果当前差或相等更小,则更新。//遍历[1,r],肯定能找出最优的x=i;
{
mls=ls;
mrs=rs;
ans=i;
}
}
printf("%lld\n",ans);
}
return 0;
}</span>