#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[N]; 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) */