在學校的入口處有一個巨大的矩形廣告牌,高爲h,寬爲w。所有種類的廣告都可以貼,比如ACM的廣告啊,還有餐廳新出了哪些好喫的,等等。。
在9月1號這天,廣告牌是空的,之後廣告會被一條一條的依次貼上去。
每張廣告都是高度爲1寬度爲wi的細長的矩形紙條。
貼廣告的人總是會優先選擇最上面的位置來帖,而且在所有最上面的可能位置中,他會選擇最左面的位置,而且不能把已經貼好的廣告蓋住。
如果沒有合適的位置了,那麼這張廣告就不會被貼了。
現在已知廣告牌的尺寸和每張廣告的尺寸,求每張廣告被貼在的行編號。
Input
多組樣例,不超過40個。
對每組樣例,第一行包含3個整數h,w,n(1 <= h,w <= 10^9; 1 <= n <= 200,000) -廣告牌的尺寸和廣告的個數。
下面n行每行一個整數 wi (1 <= wi <= 10^9) - 第i張廣告的寬度.
Output
對每張廣告,輸出它被貼在的行編號(是1到h之間的數),頂部是第一行。如果某廣告不能被貼上,則輸出-1。
Sample Input
3 5 5
2 4 3 3 3
Sample Output
1
2 1 3 -1
題目大意:有一個h*w的公告板,要往上面放n個廣告,每個廣告寬爲1,長爲w[i],優先放在上面,從左邊放起。
問題不難,簡單的線段樹模板題,
用父節點保存子節點剩餘的最大的廣告長度。
#include <cstdio>
#include <limits.h>
#include <string.h>
#include <math.h>
#include <algorithm>
using namespace std;
int tree[800003];
int h,w,n,x;
int Query(int num,int l,int r,int wi){ //num是當前節點,[l,r]是當前節點區間,wi是廣告的長度
if (l==r) { //如果l==r則說明到達葉子節點
tree[num]-=x; //把節點上的長度減掉x
return l; //返回節點編號
}
int m=(l+r)>>1;
int res=0;
if (tree[num<<1]>=wi) res=Query(num<<1,l,m,wi); //優先查詢左子樹
else res=Query(num<<1|1,m+1,r,wi);
tree[num]=max(tree[num<<1],tree[num<<1|1]); //更新父節點的值
return res; //返回查詢到的節點編號
}
int main(){
while (scanf("%d%d%d",&h,&w,&n)!=EOF)
{
if (h>n) h=n; //不可能用到比n更多的行數
for (int i=1; i<(h<<2); i++) tree[i]=w; //相當於建樹
while (n--)
{
scanf("%d", &x);
if (tree[1]<x) printf("-1\n"); //總區間的最大值小於廣告長度,則無法放置
else printf("%d\n", Query(1,1,h,x)); //查詢[1,h]
}
}
return 0;
}