Hdu2795-Billboard-【線段樹】-【有】

傳送門:http://acm.hdu.edu.cn/showproblem.php?pid=2795


不貼英文題了,,貼了也沒用( ╯□╰ )  翻譯之後看了好久才理解題意

中文題意:

在學校的入口處有一個巨大的矩形廣告牌,高爲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。
在學校的入口處有一個巨大的矩形廣告牌,高爲h,寬爲w。所有種類的廣告都可以貼,比如ACM的廣告啊,還有餐廳新出了哪些好喫的,等等。。
Sample Input
3 5 5
2
4
3
3
3
Sample Output
1
2
1
3
-1

 
在9月1號這天,廣告牌是空的,之後廣告會被一條一條的依次貼上去。
 
每張廣告都是高度爲1寬度爲wi的細長的矩形紙條。
 
貼廣告的人總是會優先選擇最上面的位置來帖,而且在所有最上面的可能位置中,他會選擇最左面的位置,而且不能把已經貼好的廣告蓋住。

如果沒有合適的位置了,那麼這張廣告就不會被貼了。
 
現在已知廣告牌的尺寸和每張廣告的尺寸,求每張廣告被貼在的行編號。


解題:感覺今天學的樹狀結構根本沒用到2333     首先每個廣告的高度都是1  可以將整個廣告旋轉90°,這時可以將高作爲端點,寬w作爲端點值,,這樣一個線段樹就出來了  很神奇

利用線段樹的思想,先以每一行的長度即矩形的寬度爲葉子節點建立一個樹,每一個非葉子節點表示該節點所在區間的剩餘的最大長度,建好樹之後我們得到的樹的根節點表示的是整個矩形的剩餘的最大長度(可能是廣告牌的寬,也可能是最大的剩餘寬),根據這個條件就可以直接得到該條廣告是否能夠寫上去,能寫上去的話我們可以直接更新和這個葉子節點有關的所有節點。

當某個廣告的寬度wi不大於整段的最大值時(更新之後),一定能放進去,因爲h大於n時一定有空餘的行數  小於時如果不大於最大的空閒空間,就能放進去。

貼一個感覺很有心的博主關於線段樹http://blog.csdn.net/metalseed/article/details/8039326

#include<cstdio>
#include<algorithm>
using namespace std;
struct Node
{
	int l,r,maxw;//表示剩餘空間的最大值 
}Tree[200005<<2];
int h,w,n,ans;
void PushUp(int o)
{
	Tree[o].maxw =max(Tree[o*2].maxw ,Tree[o*2+1].maxw );
}
void Build(int o,int l,int r)
{
	Tree[o].l =l;
	Tree[o].r =r;
	Tree[o].maxw =w;//每一個葉子節點在開始的時候的長度就是他的最大長度,即矩形的寬度
	if(l==r)
		return ;
	int mid=(l+r)>>1;
	Build(o*2,l,mid);
	Build(o*2+1,mid+1,r);
//	PushUp(o);
}
void Query(int o,int l,int r,int x)
{
	if(Tree[o].l ==Tree[o].r)
	{
		Tree[o].maxw -=x;		//查詢到葉子結點時更新節點, 
//		return Tree[o].l;		即每次查找到這個點,就將這個長度減去,表示只剩下這些空間 
		ans=Tree[o].l ;  // 返回所在的葉子的位置,即矩形的行位置
		return ;
	}
	int mid=(l+r)>>1;
	if(x<=Tree[o*2].maxw )		//如果寬度小於左節點,,就去左找,總之優先左節點 
		Query(o*2,l,mid,x);
	else
		Query(o*2+1,mid+1,r,x); 
	PushUp(o); 
	
}
int main()
{
	while(scanf("%d%d%d",&h,&w,&n)!=EOF)
	{
		h=min(h,n);//節省空間   因爲如果 h 比 n 大  只取小的就行  多了也用不完 
		Build(1,1,h);
		for(int i=1; i<=n; i++)
		{
			int t;
			scanf("%d",&t);
			if(Tree[1].maxw <t)		//Tree[1].maxw  是跟結點一定是最大值 
			{
				printf("-1\n");
				continue;
			}
			else
			{
				Query(1,1,h,t);// h 就是模板裏的 n 
				printf("%d\n",ans);
			} 
		}
	}
	return 0;
}
/*
Sample Input

    3 5 5
    2
    4
    3
    3
    3

Sample Output

    1
    2
    1
    3
    -1
*/


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章