MiYu原创, 转帖请注明 : 转载自 ______________白白の屋
题目地址:
http://acm.hdu.edu.cn/showproblem.php?pid=2795
题目描述:
Billboard
Time Limit: 20000/8000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 733 Accepted Submission(s): 340
On September 1, the billboard was empty. One by one, the announcements started being put on the billboard.
Each announcement is a stripe of paper of unit height. More specifically, the i-th announcement is a rectangle of size 1 * wi.
When someone puts a new announcement on the billboard, she would always choose the topmost possible position for the announcement. Among all possible topmost positions she would always choose the leftmost one.
If there is no valid location for a new announcement, it is not put on the billboard (that's why some programming contests have no participants from this university).
Given the sizes of the billboard and the announcements, your task is to find the numbers of rows in which the announcements are placed.
The first line of the input file contains three integer numbers, h, w, and n (1 <= h,w <= 10^9; 1 <= n <= 200,000) - the dimensions of the billboard and the number of announcements.
Each of the next n lines contains an integer number wi (1 <= wi <= 10^9) - the width of i-th announcement.
3 5 5 2 4 3 3 3
1 2 1 3 -1
一开始没想明白怎么做 , 仔细想了想, 再次 读题后 发现 , n <= 200000; 也就是说 最多 也就 200000 条广告 , 你就算每行贴一张 ,
最多也就贴到 200000 行, 所以 不要被 h <= 10^9 次方吓到了 ,认为 线段树开不了那么大的数组 . 只要开 200000 就可以了 .
其他的 没什么 好说的 , 知道这个 就直接 暴 吧 ............将近 7000MS .=水过................. g++提交 还华丽的 送出了 一次 TLE....
C++ 水过了 ............
// 一直没明白 为什么我的 代码速度 那么 慢, 查询后 更新 的时间是 2000MS 左右 , 我的 是 查询 就更新了,
竟然要 将近 7000MS ? 非常 郁闷 , 不信邪的 继续 检查 代码, 在 瞪了 1哥小时后 , 忽然想到 : 把 cout 改成
printf 会怎样? 结果 : 1640 MS AC ..............鬼知道他的 数据量有多大..... cout 和 printf
竟然 差了 5000 MS 的时间 ...........无语
代码如下 :
/*
Coded By : MiYu
Link : http://www.cnblogs.com/MiYu || http://www.cppblog.com/MiYu
Author By : MiYu
Test : 1
Program : 2795
*/
//#pragma warning( disable:4789 )
#include <iostream>
#include <algorithm>
#include <string>
#include <set>
#include <map>
#include <utility>
#include <queue>
#include <stack>
#include <list>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
using namespace std;
struct ADV {
int left, right, val;
int mid () { return ( left + right ) >> 1; }
}adv[800000];
int N, W, H, w;
void creat ( int l, int r, int rt = 1 ){
adv[rt].left = l;
adv[rt].right = r;
adv[rt].val = W;
if ( l == r )
return ;
int mid = adv[rt].mid();
creat ( l, mid, rt << 1 );
creat ( mid + 1, r, ( rt << 1 ) + 1 );
}
void add ( int rt = 1, int wei = w ){
if ( wei <= adv[rt].val ){
if ( adv[rt].left == adv[rt].right ){
adv[rt].val -= wei;
//cout << adv[rt].left << endl; //杯具的 地方
printf ( "%d\n", adv[rt].left );
return ;
} else if ( adv[rt<<1].val >= wei ) {
add ( rt << 1 );
adv[rt].val = max ( adv[rt<<1].val, adv[(rt<<1)+1].val );
} else {
add ( ( rt << 1 ) + 1 );
adv[rt].val = max ( adv[rt<<1].val, adv[(rt<<1)+1].val );
}
} else {
//cout << -1 << endl; //杯具的地方
puts ( "-1" );
}
}
inline bool scan_ud(int &num)
{
char in;
in=getchar();
if(in==EOF) return false;
while(in<'0'||in>'9') in=getchar();
num=in-'0';
while(in=getchar(),in>='0'&&in<='9'){
num*=10,num+=in-'0';
}
return true;
}
int main ()
{
while ( scan_ud (H)&&scan_ud (W)&&scan_ud (N) ) {
if ( H > 200000 )
H = 200010;
creat ( 1, H );
for ( int i = 1; i <= N; ++ i ) {
scan_ud (w);
add ( );
}
}
return 0;
}
另 附上 傻崽 神牛 代码 :
#include <iostream>
#include <algorithm>
#include <string>
#include <set>
#include <map>
#include <utility>
#include <queue>
#include <stack>
#include <list>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#define FF(i,a) for( int i = 0 ; i < a ; i ++ )
#define FOR(i,a,b) for( int i = a ; i < b ; i ++ )
#define LL(a) a<<1
#define RR(a) a<<1|1
template<class T> inline void checkmin(T &a,T b) {if(a < 0 || a > b)a = b;}
template<class T> inline void checkmax(T &a,T b) {if(a < b) a = b;}
using namespace std;
struct Node {
int val;
int idx;
friend bool operator < (Node a , Node b) {
if(a.val == b.val) {
return a.idx > b.idx;
}
return a.val < b.val;
}
}error;
struct Seg_Tree{
int left,right;
Node node;
int mid() {
return (left + right)>>1;
}
}tt[800000];
int n , h , m;
void build(int l,int r,int idx) {
tt[idx].left = l;
tt[idx].right = r;
tt[idx].node.idx = l;
tt[idx].node.val = h;
if(l == r) return ;
int mid = tt[idx].mid();
build(l,mid,LL(idx));
build(mid+1,r,RR(idx));
}
void update(int l,int r,int val,int idx) {
if(l <= tt[idx].left && r >= tt[idx].right) {
tt[idx].node.val += val;
return ;
}
int mid = tt[idx].mid();
if(l <= mid) update(l,r,val,LL(idx));
if(mid < r) update(l,r,val,RR(idx));
tt[idx].node = max(tt[LL(idx)].node,tt[RR(idx)].node);
}
Node query(int w,int idx) {
if(tt[idx].node.val < w) {
return error;
}
if(tt[idx].left == tt[idx].right) {
return tt[idx].node;
}
if(tt[LL(idx)].node.val >= w) {
return query(w,LL(idx));
} else {
return query(w,RR(idx));
}
}
int main() {
error.idx = -1;
while(scanf("%d%d%d",&n,&h,&m) == 3) {
checkmin(n,m);
build(1,n,1);
while(m --) {
int w;
scanf("%d",&w);
Node ret = query(w,1);
printf("%d\n",ret.idx);
if(ret.idx != -1) {
update(ret.idx,ret.idx,-w,1);
}
}
}
return 0;
}