1. 程式人生 > 實用技巧 >Billboard(線段樹) HDU - 2795

Billboard(線段樹) HDU - 2795

At the entrance to the university, there is a huge rectangular billboard of size h*w (h is its height and w is its width). The board is the place where all possible announcements are posted: nearest programming competitions, changes in the dining room menu, and other important information.

On September 1, the billboard was empty. One by one, the announcements started being put on the billboard.


Each announcement is a stripe of paper of unit height. More specifically, the i-th announcement is a rectangle of size 1 * wi.

When someone puts a new announcement on the billboard, she would always choose the topmost possible position for the announcement. Among all possible topmost positions she would always choose the leftmost one.

If there is no valid location for a new announcement, it is not put on the billboard (that's why some programming contests have no participants from this university).

Given the sizes of the billboard and the announcements, your task is to find the numbers of rows in which the announcements are placed.


題意:

在學校的入口處有一個巨大的矩形廣告牌,高為h,寬為w。所有種類的廣告都可以貼,比如ACM的廣告啊,還有餐廳新出了哪些好吃的,等等。。 在9月1號這天,廣告牌是空的,之後廣告會被一條一條的依次貼上去。 每張廣告都是高度為1寬度為wi的細長的矩形紙條。 貼廣告的人總是會優先選擇最上面的位置來帖,而且在所有最上面的可能位置中,他會選擇最左面的位置,而且不能把已經貼好的廣告蓋住。 如果沒有合適的位置了,那麼這張廣告就不會被貼了。 現在已知廣告牌的尺寸和每張廣告的尺寸,求每張廣告被貼在的行編號。
思路:以廣告牌的高度進行劃分建樹,記錄每層的剩餘寬度的最大值, 例如 tree[1].len是1-N層最大的剩餘寬度, tree[1*2].len是1-(1+N)/2層的最大剩餘寬度 tree[1*2+1].len是(1+N)/2-N層的最大剩餘寬度
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstring>
#include<stdio.h>
#include<algorithm>
#include<map>
#include<queue>
#include<set>
#include <sstream>
#include<vector>
#include<cmath>    
#include<stack>
#include<time.h>
#include<ctime>
using namespace std;
#define inf 1<<30
#define eps 1e-7
#define LD long double
#define LL long long
#define maxn 1000005
int s[maxn] = {};    
int h, w, n, ans = -1;
struct node
{
    int L, R, len;
}tree[maxn];
void up(int step)
{
    tree[step].len = max(tree[step << 1].len, tree[step << 1 | 1].len);
}
void build(int step, int L, int R)//建樹
{
    tree[step].L = L;
    tree[step].R = R;
    if (tree[step].L == tree[step].R)
    {
        tree[step].len = w;//L層的寬度為w
        return;
    }
    int mid = (L + R) >> 1;
    build(step << 1, L, mid);
    build(step << 1 | 1, mid + 1, R);
    up(step);//更新
}
void treeInsert(int step, int k)//插入
{
    if (tree[step].L == tree[step].R)
    {
        tree[step].len -= k;//貼完廣告後,這一層要減去廣告佔用的空間
        ans = tree[step].L;//記錄層數
        return;
    }
    if (k <= tree[step << 1].len)
        treeInsert(step << 1, k);
    else
        treeInsert(step << 1 | 1, k);
    up(step);//更新
}
int main()
{
    while (~scanf("%d%d%d", &h, &w, &n))
    {
        if (h > n)
        {
            h = n;
        }
        build(1, 1, h);
        int k;
        for (int i = 1; i <= n; i++)
        {
            scanf("%d", &k);
            ans = -1;//更新
            if (k <= tree[1].len)
            {        
                treeInsert(1, k);
            }
            printf("%d\n", ans);
        }
    }
}