UVALive 7261 Xiongnu's Land (扫描线)
Wei Qing (died 106 BC) was a military general of the Western Han dynasty whose campaigns against the Xiongnu earned him great acclaim. He was a relative of Emperor Wu because he was the younger half-brother of Empress Wei Zifu (Emperor Wu’s wife) and the husband of Princess Pingyang. He was also the uncle of Huo Qubing, another notable Han general who participated in the campaigns against the Xiongnu and exhibited outstanding military talent even as a teenager.
Defeated by Wei Qing and Huo Qubing, the Xiongnu sang: “Losing my Qilian Mountains, made my cattle unthriving; Losing my Yanzhi Mountains, made my women lacking rouge.”
The text above is digested from Wikipedia. Since Wei and Huo’s distinguished achievements, Emperor Wu decided to give them some awards — a piece of land taken by them from Xiongnu. This piece of land was located in a desert, and there were many oases in it. Emperor Wu wanted to draw a straight south-to-north dividing line to divide the land into two parts, and gave the western part to Wei Qing while gave the eastern part to Huo Qubing. There are two rules about the land dividing:
1. The total area of the oases lay in Wei’s land must be larger or equal to the total area of the oases lay in Huo’s land, and the difference must be as small as possible.
2. Emperor Wu wanted Wei’s land to be as large as possible without violating the rule 1
To simplify the problem, please consider the piece of land given to Wei and Huo as a square on a plane. The coordinate of its left bottom corner was (0, 0) and the coordinate of its right top corner was (R, R). Each oasis in this land could also be considered as a rectangle which was parallel to the coordinate axes. The equation of the dividing line was like x = n, and n must be an integer. If the dividing line split an oasis, then Wei owned the western part and Huo owned the eastern part. Please help Emperor Wu to find out how to draw the dividing line.
Input
The first line of the input is an integer K meaning that there are K (1 ≤ K ≤ 15) test cases.
For each test case:
The first line is an integer R, indicating that the land’s right top corner was at (R, R) (1 ≤ R ≤ 1, 000, 000)
Then a line containing an integer N follows, indicating that there were N (0 < N ≤ 10000) oases.
Then N lines follow, each contains four integers L, T, W and H, meaning that there was an oasis whose coordinate of the left top corner was (L, T), and its width was W and height was H. (0 ≤ L, T ≤ R, 0 < W, H ≤ R). No oasis overlaps.
Output
For each test case, print an integer n, meaning that Emperor Wu should draw a dividing line whose equation is x = n. Please note that, in order to satisfy the rules, Emperor might let Wei get the whole land by drawing a line of x = R if he had to.
Sample Input
2
1000
2
1 1 2 1
5 1 2 1
1000
1
1 1 2 1
Sample Output
5
2
题意:有多个矩形分布在[0, 0]到[R, R]的的范围内。 画一条竖线分割成两块矩形,使得左边包括矩形的面积大于等于右边的面积。 在这个前提下使得画的竖线尽量远。
题解:复杂度分析:从所给数据范围看,R在106数量级,既然n取[0,R]的整数,那么若以R为数据规模,对x=i, i:0~R进行步长为1的线性扫描,假设每次迭代中基本操作次数为常数,则渐进复杂度为O(n)。 假设计算环境1000ms的时间可完成108规模的基本运算,则本题O(n)的线性扫描思路从渐进复杂度的意义上讲是可行的。 确定了线性扫描的思路,接下来要考虑如何把每轮迭代代价控制在常数以及扫描停止的条件。 1. 如果在每轮迭代中,都检查所有N个绿洲以求出所划分的面积,那么每轮迭代的复杂度为T(N),整体复杂度上升到了T(N*R), 即1010显然不可行。 此方法的低效在于它没有为线性扫描这一“算法”设计合适的“数据结构”来存放绿洲的数据。 题目输入的绿洲是一个个分散的个体,而从坐标出发的线性扫描需要快速获得以扫描位置 x=i 为自变量的左侧累加面积,这一“快速”,常数最好,至少不能和N在同一数量级。 因此,要进行预处理将原始的绿洲数据转换为以横坐标为中心的统计值,以使每次迭代能用1~2个基本操作得到当前累加面积进而判断下一步的走向。 2. 扫描可以从最左侧的x=0开始,不断向右移动(保证绿洲面积左侧 < 右侧)。 遇到第一个理想位置(左侧>=右侧,满足了(1))后继续试探,直至抵达最理想的位置(左侧绿洲面积不增的条件下,为满足(2)尽量再往右移动)停止。 由于扫描是线性的,可利用一个累加变量,每次只取当前“列”的面积作累加即可。 至此,对绿洲数据的预处理结果要求已经比较明确了。 即得到 x=i 代表的一段宽度为1(可以是i ~ i+1),高度为R的土地中绿洲的总面积,不妨用x[i]表示。 那么这段预处理所花费的时间呢,这回要以N为数据规模来考虑,假设所有绿洲被读入结构体数组中,则对j:0~N-1进行步长为1的线性扫描,假设每次迭代中基本操作次数为常数,N在104数量级,完全可行。 但处理每个绿洲真的是常数时间吗,其实应该是T(W),因为要把宽度切分为长度为1的W段,累加到x数组的W个元素上。除非x用的不是朴素的一维数组,否则整体的渐进复杂度应为O(N*W),又是1010。
#include <cstdio>
#include <cstring>
using namespace std;
const int MAX_R = ;
const int MAX_N = ; int K;
int R, N;
struct Rec{
int L, T;
long long W, H; //注意类型!!
}rec[MAX_N];
int x[MAX_R]; int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
scanf("%d",&K);
while(K--){
scanf("%d",&R);
scanf("%d",&N);
memset(x,,sizeof(x));
long long sum = ;
for(int i=; i<N; i++){
scanf("%d%d%d%d",&rec[i].L,&rec[i].T,&rec[i].W,&rec[i].H);
sum += rec[i].W*rec[i].H;
for(int j=rec[i].L; j<rec[i].L+rec[i].W; j++)
x[j] += rec[i].H;
}
long long wei = ;
int i;
for(i=; wei* < sum; i++)
wei += x[i];
while(x[i]== && i<R) i++;
printf("%d\n",i);
}
return ;
}
UVALive 7261 Xiongnu's Land (扫描线)的更多相关文章
- UVALive - 7261 Xiongnu's Land
思路: 先二分下界,再二分上届. #include <bits/stdc++.h> using namespace std; #define MP make_pair #define PB ...
- (UVALive 7261)Xiongnu's Land 二分
题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_ ...
- 2015北京区域赛 Xiongnu's Land
Wei Qing (died 106 BC) was a military general of the Western Han dynasty whose campaigns against the ...
- [ An Ac a Day ^_^ ] HihoCoder 1249 Xiongnu's Land 线性扫描
拿到了icpc北京站的参赛名额 感谢亮哥~ 虽然是地狱之战 但也要全力以赴! 题意: 有一片沙漠 n片绿洲 让你用一条线分成两部分 左≥右 而且分割线要尽量靠右 问线的位置 思路: 网上说可以二分 没 ...
- 【UVALive】3905 Meteor(扫描线)
题目 传送门:QWQ 分析 扫描线搞一搞. 按左端点排序,左端点相同时按右端点排序. 如果是左端点就$ cnt++ $,否则$ cnt-- $ 统计一下$ Max $就行了 代码 #include & ...
- 二分+贪心 hihocoder 1249 Xiongnu's Land (15北京A)
题目传送门 题意:有多个矩形分布在[0, 0]到[R, R]的的范围内,画一条竖线分割成两块矩形,使得左边包括矩形的面积大于等于右边的面积,在这个前提下使得画的竖线尽量远 分析:二分答案,当面积相等时 ...
- 【hihocoder 1249 Xiongnu's Land】线性扫描
2015区域赛北京赛区的三水,当时在赛场上没做出的原因是复杂度分析不正确导致把方法想复杂了.近来复习复杂度分析,觉得不能只是笼统地看渐进复杂度(big-O),更应根据算法的伪码计算真正的以基本操作数为 ...
- hiho1249 Xiongnu's Land
题目链接:http://hihocoder.com/problemset/problem/1249 题目大意:有一个大正方形里面有好多不重叠的小矩形,怎么找出一条竖线分割这个正方形,使得两边的矩形面积 ...
- UVALive 4221 Walk in the Park 扫描线
Walk in the Park 题目连接: https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemi ...
随机推荐
- 似然估计中为什么要取对数以GMM为例
1.往往假设特征之间独立同分布,那么似然函数往往是连城形式,直接求骗到不好搞,根据log可以把连乘变为连加. 2.另外概率值是小数,多个小数相乘容易赵成浮点数下溢,去log变为连加可以避免这个问题. ...
- Web 测试经验总结
Web功能测试常用方法 1.页面链接检查每一个链接是否都有对应的页面,并且页面之间切换正确: 2.相关性检查删除/增加一项会不会对其他项产生影响,如果产生影响,这些影响是否都正确. 3.检查按钮的功能 ...
- appium-向右滑动定位
上面5幅欢迎图,要向右滑动4次再点击[立即体验]才可以到首屏 #首页欢迎图滑动4次 for i in range(4): driver.swipe(1200, 200, 10, 200, 1500) ...
- eclipse中新建python项目报错:Project interpreter not specified
eclipse-windows-preferences-python
- 求三数中Max和猜拳游戏
方法一: Console.WriteLine("请输入三个数字:"); int a = int.Parse(Console.ReadLine()); int b = int.Par ...
- Boost的状态机库教程(1)
介绍 Boost状态机库一个应用程序框架,你可以用它将UML状态图快速的转换为可执行的c++代码,而不需要任何的代码生成器.它支持几乎所有的UML特征,可以直接了当的转换,并且转换后的c++代码就像对 ...
- spring mvc实现登录+异常
登录页面login.jsp在webroot下 <body> <form action="user/login" method="post"&g ...
- iOS学习笔记—ViewController/生命周期
ViewController是iOS应用程序中重要的部分,是应用程序数据和视图之间的重要桥梁,ViewController管理应用中的众多视图.iOS的SDK中提供很多原生ViewController ...
- linux find 命令详解
Linux下 利用find命令删除所有vssver2.scc文件 删除所有vssver2.scc文件 这是我当初查找 Linux find 命令的目的所在 1) find / -name ‘vssv ...
- bat programming is easy and powerful
用linux的角度来思考windows,习惯了linux的shell后, 再来看windows的bat编程,就简单多了,简直就是理所当然 实际上windows的cmd命令行和linux的shell命令 ...