题意:
一个board的面积是h*w..在上面贴一些announcement..
给出告示的宽度ww..可知告示的面积为1*ww..
问告示是否可以贴上去..可以就输出在board的第几行..不可以就输出-1
思路:
以min(h, n)为长度建一棵树..
然后每一个的叶子的长度为w..
找出所有叶子中最大的那个..把announcement贴上去..
用ma数组存当前区间最大值..
Tips:
查询和更新可以一起写..但是我分开写了..
然后还有一个要注意的是..树的最大宽度为min(h, n)
比较的时候是和左右节点大小比..
※ 所以modify的时候判断条件也应该是if(x > ma[rt<<1])..
Code:
View Code
1 #include <stdio.h> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 6 const int MAXN = 200010; 7 int ma[MAXN<<2]; 8 int h, w, n; 9 10 void pushup(int rt) 11 { 12 ma[rt] = max(ma[rt<<1], ma[rt<<1|1]); 13 } 14 15 void creat(int l, int r, int rt) 16 { 17 ma[rt] = w; 18 if(l == r) 19 return; 20 int mid = (l+r)>>1; 21 creat(l, mid, rt<<1); 22 creat(mid+1, r, rt<<1|1); 23 } 24 25 void modify(int p, int ww, int l, int r, int rt) 26 { 27 if(l == r) { 28 ma[rt] += ww; 29 return; 30 } 31 int mid = (l+r)>>1; 32 if(p <= mid) modify(p, ww, l, mid, rt<<1); 33 else modify(p, ww, mid+1, r, rt<<1|1); 34 pushup(rt); 35 } 36 37 int query(int x, int L, int R, int rt) 38 { 39 if(L == R) { 40 return L; 41 } 42 int mid = (L+R)>>1; 43 int res = 0; 44 if(x <= ma[rt<<1]) query(x, L, mid, rt<<1); 45 else query(x, mid+1, R, rt<<1|1); 46 } 47 48 int main() 49 { 50 int i, j; 51 int ww; 52 int ans; 53 while(scanf("%d %d %d", &h, &w, &n) != EOF) 54 { 55 if(h > n) h = n; 56 creat(1, h, 1); 57 58 for(i = 0; i < n; ++i) { 59 scanf("%d", &ww); 60 if(ww > ma[1]) puts("-1"); 61 else { 62 ans = query(ww, 1, h, 1); 63 printf("%d\n", ans); 64 modify(ans, -ww, 1, h, 1); 65 } 66 67 } 68 } 69 return 0; 70 }