hdu2795 Billboard ——线段树入门题
April 24, 2013
Hdu
Data Structure
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2795 题目大意: 高度为h,长度为w的板子,贴n个海报,每个海报的高度都为1,长度由n个整数给出。贴海报的原则是,从高到低,优先选高的,从左到右,优先选右边的位置。起初每个海报在板子上所在的行数。 题目思路: 建立一棵叶子节点有h个的线段树,每个节点代表这个区间内的最大值,最开始,叶子节点都是w。然后每插入一个值就插入到叶子节点,输出叶子节点的值,然后更新父节点。 这道题目的难点是,要想到建立线段树,把模型抽象出来。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <cmath>
#include <algorithm>
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
using namespace std;
typedef long long int LL;
const int MAXN = 0x3f3f3f3f;
const int MIN = -0x3f3f3f3f;
const double eps = 1e-9;
const int dir[8][2] = {{0,1},{1,0},{0,-1},{-1,0},{-1,1},
{1,1},{1,-1},{-1,-1}};
const int MAX = 200000+10;
int a[MAX<<2], n, h, w, b[MAX];
void pushup(int rt)
{
a[rt] = max(a[rt<<1], a[rt<<1|1]);
}
void build(int l, int r, int rt)
{
if (l == r) { a[rt] = w; return; }
int m = (l + r) >> 1;
build(lson); build(rson); pushup(rt);
}
void update(int p, int k, int l, int r, int rt)
{
if (l == r) { a[rt] -= k; return; }
int m = (l + r) >> 1;
if (p <= m) update(p, k, lson);
else update(p, k, rson);
pushup(rt);
}
int query(int k, int l, int r, int rt)
{
if (l == r) { return l; }
int m = (l + r) >> 1, ret = 0;
/*
if (a[rt<<1] >= k) ret = query(k, lson);
else ret = query(k, rson);
*/
if (a[rt] >= k) {
if (a[rt<<1] >= k) ret = query(k, lson);
else ret = query(k, rson);
}
else return 0;
return ret;
}
int main(void){
#ifndef ONLINE_JUDGE
freopen("hdu2795.in", "r", stdin);
#endif
int i, j, k;
while (~scanf("%d%d%d", &h, &w, &n)){
if (h > n) h = n;
build(1, h, 1);
for (i = 0; i < n; ++i) {
scanf("%d", b + i);
if (a[1] < b[i]) { printf("-1\n"); continue; }
k = query(b[i], 1, h, 1);
printf("%d\n", k); update(k, b[i], 1, h, 1);
}
}
return 0;
}
注释掉的两行代码也是可以的,只不过是以前抄的NOTONLYSUCCESS的。其实思想是一样的。还是谢谢HH神牛,线段树就是看着他的博客学的。