hdu 2795 Billboard 线段树
题意:
给出公告板的高和宽h,w,现在要粘贴公告(每条公告高度为1),粘贴在能粘贴的最上面的位置。给出n个公告的宽度,顺序粘贴,让你求每个公告在第几行。
分析:
n最大为200000,不可能每次顺序地遍历。我们可以用线段树来记录每一行的剩余的宽度。但是行数h最大有10^9方,不可能开这么大的数组呀。我们再看看公告条数n的范围,每一个公告条要么占据了一行,要么就贴不上去,也就是说所需要的行数最大为n,当h>n时,把n赋值给h就可以了。
这里的查询和更新都是对单点进行操作,所以可以合并到一起
query:边查询边更新
#include <bits/stdc++.h> #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 using namespace std; const int MAXN = 200008; int maxw[MAXN<<2]; int h,w; void build(int l, int r, int rt) { if(l == r) { maxw[rt] = w; return; } int m = (l + r) >> 1; build(lson); build(rson); maxw[rt] = max(maxw[rt<<1], maxw[rt<<1|1]); } int query(int wid, int l, int r, int rt) { if(maxw[rt] < wid) return -1; if(l == r) { maxw[rt] -= wid; return l; } int m = (l + r) >> 1; int ret = query(wid, lson); if(ret == -1) ret = query(wid, rson); maxw[rt] = max(maxw[rt<<1], maxw[rt<<1|1]); return ret; } int a[MAXN]; int main() { // freopen("in.txt", "r", stdin); int n, wid; while(~scanf("%d%d%d", &h, &w, &n)) { if(h > n) h = n; build(1, h, 1); for(int i=0; i<n; i++) { scanf("%d", &wid); printf("%d\n",query(wid, 1, h, 1)); } } return 0; }