比赛描述
南二有一个巨大的长方形公告牌,尺寸为h×w(h是它的高度,w是它的宽度)。牌子上可以张贴一切可能的告示:最近ACM程序设计竞赛通知,食堂菜单的变化,以及其他重要信息。
在9月1日,公告牌是空的。告示一个接一个地张贴在广告牌上。
每个告示是单位高度的纸条。具体地说,第i个告示是一个大小1 ×wi的矩形。当有人在公告牌上贴出一个新的告示,他永远选择尽可能上的位置。在所有可能的最高位置,她将永远选择最左边的一个。
如果没有有效的位置来贴一个新的告示,则不放在公告牌上。给定公告牌的大小,你的任务是找到告示放置的行数。
输入
输入文件的第一行包括三个整数:h, w, 和 n (1 ≤ h,w ≤ 109; 1 ≤ n ≤ 200 000) —表示公告牌的大小和告示的数目。
下面n行,每行包括一个整数wi (1 ≤wi ≤ 109) 表示 第i个告示的宽度。
输出
对于每个告示(按照它们在输入文件中给定的顺序)输出一个值 — 这个告示放置的行数。行从1到h标识,从顶行开始。如果一个告示不能放置于告示牌,则输出“-1”。
注意:输出部分的结尾要求包含一个多余的空行。
样例输入
3 5 5
2
4
3
3
3
样例输出
1
2
1
3
-1
题目来源
“IBM南邮杯”个人赛2009
#include<iostream> #define MAX_N 1000000 using namespace std; int h,w; struct{ int l,r,num; }node[MAX_N<<2]; void build(int i, int l, int r){ node[i].l = l; node[i].r = r; node[i].num = w; if(l==r){ return; } int mid = (l+r)>>1; build((i<<1)|1, l, mid); build((i+1)<<1, mid+1, r); } int insert(int i, int wi){ if(node[i].num < wi){ return -1; } if(node[i].l==node[i].r){ node[i].num -= wi; return node[i].l; } int result = insert((i<<1)|1, wi); if(result == -1){ result = insert((i+1)<<1,wi); } if(result != -1){ node[i].num = max(node[(i<<1)|1].num, node[(i+1)<<1].num); } return result; } int main(){ int n,wi; scanf("%d%d%d",&h,&w,&n); build(0, 1, min(h,n)); while(n--){ scanf("%d",&wi); printf("%d\n",insert(0,wi)); } }