~~~题目链接~~~
题目大意:在一个高为h, 宽为w的面板上贴上n张海报, 每个海报的高都为1, 每张海报能尽可能的贴在高度最高的地方, 当同一个高度有多个地方可以贴海报时,贴在最左边, 现在求每个海报能贴在哪个高度。
思路:用线段树进行2分区间, 把高度看成区间。区间的高度为最小的(h, n), 注意n == 1时;
code:
#include <stdio.h> #define N 200002 #define max(a,b) a>b? a:b using namespace std; struct node { int id, w; }t[4*N]; int h = 0, w = 0, n = 0, cnt = 0, flag = 0; void build(int c, int l, int r)//区间的值存当前所有叶子节点中能剩余贴的地方的最大宽度 { int m = l+(r-l)/2; if(l == r) { t[c].id = cnt++; t[c].w = w; return ; } build(2*c, l, m); build(2*c+1, m+1, r); t[c].w = max(t[2*c].w, t[2*c+1].w); } int query(int c, int l, int r, int w) { int num = -1; int m = l+(r-l)/2; if(t[c].w<w) return -1; if(l == r ) { t[c].w -= w; return t[c].id; } if(t[2*c].w>=w) num = query(2*c, l, m, w); else if(t[2*c+1].w>=w) num = query(2*c+1, m+1, r, w); t[c].w = max(t[2*c].w, t[2*c+1].w); return num; } int main() { int i = 0, min = 0, num[N]; while(scanf("%d %d %d", &h, &w, &n) != EOF) { min = h<n? h:n; build(1, 1, min); for(i = 0; i<n; i++) { cnt = 0; int w = 0; scanf("%d", &w); flag = 0; num[i] = query(1, 1, min, w); } for(i = 0; i<n; i++) { if(num[i] == -1) printf("%d\n", num[i]); else printf("%d\n", num[i]+1); } } return 0; }