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

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));
		}
	}
}


发布了179 篇原创文章 · 获赞 5 · 访问量 20万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览