您的位置:首页 > 其它

【hihocoder1249 2015北京赛区A】【打标记线性扫描法】 Xiongnu's Land 土地划分使得左边比右边大且尽可能接近

2015-11-17 10:59 295 查看
#include<stdio.h>
#include<string.h>
typedef long long LL;
const int N=1e6+10;
int n,g;
int y,x,w,h;
int a
;
int main()
{
int T;scanf("%d",&T);
while(T--)
{
LL sum=0;
scanf("%d",&n);
memset(a,0,sizeof(a));
scanf("%d",&g);
for(int i=1;i<=g;i++)
{
scanf("%d%d%d%d",&x,&y,&w,&h);
a[x]+=h;
a[x+w]-=h;
sum+=(LL)w*h;
}
LL bot=(sum+1)/2;
LL tmp=0;
int add=0;
for(int i=1;i<n;i++)
{
add+=a[i];
tmp+=add;

//一旦达到了条件1,我们就在满足条件2的情况下尽可能右移分界线
if(tmp>=bot)
{
while(++i<n)
{
add+=a[i];
if(add)break;
}
printf("%d\n",i);
break;
}
}
}
}
/*
【trick&&吐槽】
1,打标记的数组表示横坐标每右移一位所产生的增益。数值不会超过n,用int数组存即可。

【题意】
T(1<=T<=15)组数据,
对于每组数据,给你一个大小为n*n(1<=n<=1e6)的地图,左下角为(0,0),右上角为(n,n)
然后有g(1<=g<=10000)块绿洲,坐落在这个地图上,不相交不溢出。
然后我们告诉你每块绿洲的坐标(通过给出左上角坐标及长与宽的形式)。
让你把这个地图以某个横坐标x'为界限,划分为2部分(甚至可能其中一部分的面积为0)。
使得
1,(x=x')这条线左边绿洲的面积>=(x=x')这条线右边绿洲的面积
2,在1的条件下,(x=x')这条线左边绿洲的面积与这条线右边绿洲的面积尽可能接近
3,在1和2的条件下,(x=x')这条线左边地图的面积尽可能大。

【类型】
贪心,线性扫描。

【分析】
这道题数据组数15,每组的横坐标数为1e6。
于是我们很自然地想到,如果有15*1e6的做法,这道题就可以做完了。

给定的是矩形面积,然而我们可以通过打标记的方法把它转化为线性扫描
每个绿洲,给出(x,y,w,h),
那如果我们选择的这条线在[x,x+w)范围内,每右移1,绿洲面积就会增加h,
我们的实现方法是,打标记。
那么对于一个(x,y,w,h)的绿洲,标记打为a[x]+=h,a[x+w]-=h;
表示在[x,x+w)范围内,线每右移1,绿洲面积增加h,然后在x+w和其之后,再右移就没有这个增效了。
这样我们从前向后扫描,扫描到一个>=half绿洲面积的最右位置,这道题就做完啦。

【时间复杂度&&优化】
O(Tn)

*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  hihocoder1249