您的位置:首页 > 运维架构

HDOJ-2795 Billboard [线段树][单点更新+单点查询+维护区间最值]

2012-08-12 01:00 274 查看
8s时限

单点更新+单点查询(要用区间信息来找到那个点)
注意:对于维护区间最值的, 附加域直接当主域用, 因为叶节点的最值就是那个点的值

思路:

1/ 维护区间最左的还未满w的点, 若整个区间满了, 用-1表示
这样不行的, 试想若最左未满点若剩余量还是<wi, 那怎么找下一个未满点? 几种方法都会超时.

2/ 蒟蒻啊, 看了hh的博客才知道要维护区间最大值(剩余量).  那我就维护最小值(已有量)吧...这样不用build一次..
注意: 维护最大值的初衷就是为了能够判断某区间是否有希望放wi.

另, 这题我刚想开敲的时候看了下h<= 10^9 然后sb了下想, 离散化?, 卧槽, 真是sb了, 因为h必然只需要维护到n.
因为最多n个海报每个都占一行咯.....

敲完又wa了一次....因为没考虑一进去就是叶子结点, 而叶子结点那个没判断容量是否满足.

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<string>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
inline int Rint() { int x; scanf("%d", &x); return x; }
inline int max(int x, int y) { return (x>y)? x: y; }
inline int min(int x, int y) { return (x<y)? x: y; }
#define FOR(i, a, b) for(int i=(a); i<=(b); i++)
#define FORD(i,a,b) for(int i=(a);i>=(b);i--)
#define REP(x) for(int i=0; i<(x); i++)
typedef long long int64;
#define INF (1<<30)
const double eps = 1e-8;
#define bug(s) cout<<#s<<"="<<s<<" "

// 8s时限
// 单点更新+单点查询(要用区间信息来找到那个点)
// 注意:对于维护区间最值的, 附加域直接当主域用, 因为叶节点的最值就是那个点的值

// 思路:
// 1/ 维护区间最左的还未满w的点, 若整个区间满了, 用-1表示
// 这样不行的, 试想若最左未满点若剩余量还是<wi, 那怎么找下一个未满点? 几种方法都会超时.
// 2/ 蒟蒻啊, 看了hh的博客才知道要维护区间最大值(剩余量). 那我就维护最小值(已有量)吧...这样不用build一次..
// 注意: 维护最大值的初衷就是为了能够判断某区间是否有希望放wi.

// 另, 这题我刚想开敲的时候看了下h<= 10^9 然后sb了下想, 离散化?, 卧槽, 真是sb了, 因为h必然只需要维护到n.
// 因为最多n个海报每个都占一行咯.....

#define MAXN 200002
int a[MAXN<<2]; //已有量
int W;
void pushup(int e)
{
a[e] = min(a[e<<1], a[e<<1|1]);
}
int query(int w, int l, int r, int e) //更新跟查询和在一起
{
if(l==r)
{
if(W-a[e]<w) return -1; //..........还是在外面判断比较好
a[e] += w;
return l; //返回 l, 表示位置
}
else
{
int ret; //因为回溯时要更新, 不能直接return , 故先把结果保存下来
int mid = (l+r)>>1;
if(W-a[e<<1] >= w)
ret = query(w, l, mid, e<<1);
else if(W-a[e<<1|1] >= w)
ret = query(w, mid+1, r, e<<1|1);
else
ret = -1; //无法容纳 //wa了, 错误在于若总共只有一行, 第一次就是叶子结点, 而在叶子却没考虑是否可以容纳.
pushup(e); //update
return ret;
}
}

int main()
{
int h, n;
while(scanf("%d%d%d", &h, &W, &n)!=EOF)
{
memset(a, 0, sizeof(a));
// 线段 1~min(h, n)
h = min(h, n);
REP(n)
{
int w = Rint();
//if(W-a[1] < w) puts("-1");
//if(W-a[1<<1] < w && W-a[1<<1|1] < w) puts("-1");
//else printf("%d\n", query(w, 1, h, 1));
printf("%d\n", query(w, 1, h, 1));
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  query build