题目大意是:给一个h高w宽的广告牌,和n个高为1长度为Wi的广告,广告总是选择最高位置的最左边。求每次广告放的行数是多少。
用线段树可以先判断高度是否大于n个广告,大于的话没有必要建立h高的广告牌。并使每个区间的值都为w,每次查询成功时减下Wi就行了,具体代码如下:
1 #include <iostream> 2 #include <cstdio> 3 #define lson l, m, rt<<1 4 #define rson m+1, r, rt<<1|1 5 6 using namespace std; 7 const int maxn = 2e5+10; 8 int n, h, w; 9 int MAX[maxn<<2]; 10 void PushUP(int rt){ 11 MAX[rt] = max(MAX[rt<<1], MAX[rt<<1|1]); 12 } 13 14 void build(int l, int r, int rt){//建立线段树 15 MAX[rt] = w; 16 if(l == r)return; 17 int m = (l + r) >> 1; 18 build(lson); 19 build(rson); 20 } 21 int query(int q, int l, int r, int rt){ 22 if(l == r){ 23 MAX[rt] -= q;//每次查询时减下q 24 return l; 25 } 26 int m = (l + r) >> 1; 27 int ret = (MAX[rt<<1] >= q)?query(q, lson):query(q, rson);//求出满足条件的最左边区间 28 PushUP(rt); 29 return ret; 30 } 31 32 int main() 33 { 34 while(~scanf("%d%d%d",&h,&w,&n)){ 35 if(h > n) h = n;//这样建立的区间更少些 36 build(1, h, 1); 37 while(n--){ 38 int x; 39 scanf("%d",&x); 40 if(MAX[1] < x) printf("-1 "); 41 else printf("%d ",query(x, 1, h, 1)); 42 } 43 } 44 return 0; 45 }