码迷,mamicode.com
首页 > 其他好文 > 详细

【二维线段树】20150209测试 千石抚子的三维积木

时间:2015-02-10 08:05:30      阅读:117      评论:0      收藏:0      [点我收藏+]

标签:

3. 千石抚子的三维积木(nadeko.cpp/in/out)   3.5s  512MB  10*10=100

p.s.本题含有一些(本人)黑历史,请自动过滤题目背景…= =

自从蛇切绳被搞掉之后,抚子认识到普通的蛇其实是很和谐的东西。于是她开始养蛇,有天在家无聊就开始用蛇堆积木。由于她是驯蛇高手所以它们都很听话堆上去之后就不会动,并且每条蛇可以被视为一块长方体(这个比喻有点。。好吧,接下来都把蛇叫做积木了)。

堆积木是在一块W*D的平地上进行的,每堆一个积木时会告诉你它的长宽高和放置的左上角xy坐标。

它的下底面高度等于在它没加进来之前,它所占的平面中最高的积木高度(就像三维俄罗斯方块)。

抚子想知道加入每块积木之后这块积木上底面的高度。

输入格式:

第一行三个数W,D,nW为场地的长,D为宽,n为积木数

接下来n行,每行5个数a,b,c,x,y,分别表示长宽高和放置的左上角xy坐标(注意左上角指的是平面中x,y都最小的坐标),即放置在以(x,y)-(x+a,y+b)为对角线的矩形中。(0<=x<=W,0<=y<=D)

输出格式:

n行,每行1个数表示加入这块积木之后这块积木上底面的高度。

Sample Input

7 5 4
4 3 2 0 0
3 3 1 3 0
7 1 2 0 3
2 3 3 2 2

Sample Output

2

3

2

6

数据范围:

对于30%数据  1<=n<=1000

对于50%数据  1<=n<=15000

对于100%数据  1<=n<=30000,1<=W,D<=1000 1<=每块积木的长宽高<=1000,保证放置积木的位置不会出场地的边界,输入都是整数

 

3. 千石抚子的三维积木

二维线段树。

(四分树复杂度最坏会到Q*log(W)*D

在一维情况下,跟wc2012memory的某个过程差不多。

就是要你实现两个操作,一是询问一段中最大值,二是把一段的每个元素与某个值取max

我们可以对每个线段树节点维护两个值:quanbuquan表示把这个区间全部覆盖的最大值,bu表示把这个区间部分覆盖的最大值(显然bu>=quan

那么我们就不用标记下传了;

对于询问区间全部覆盖了线段树这个区间的情况,则返回bu

对于询问区间部分覆盖了线段树这个区间的情况,则返回quan.

把一段的每个元素与某个值取max的操作类似。

 

扩展到2维的情况,则每个线段树节点又是一棵线段树(在这道题中是2棵)。

在上层线段树(也就是以x为关键字)的每个节点,要存一棵叫做quan的下层线段树(以y为关键字的),还要存一棵叫做bu的下层线段树。

相信大家多想想他们的意义就明白了。(其实就是用线段树代替了原来的变量)

更新与询问方法是类似的。

时间复杂度O(nlogWlogD)

 

#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 2004
#define lson rt<<1,l,m
#define rson rt<<1|1,m+1,r
int N,M,K,a,b,c,x,y;
struct SegmentTree
{
	int maxv[MAXN<<2],cov[MAXN<<2];
	void update(int ql,int qr,int v,int rt,int l,int r)
	  {
	  	maxv[rt]=max(maxv[rt],v);
		if(ql<=l&&r<=qr) {cov[rt]=max(cov[rt],v); return;}
		int m=l+r>>1;
		if(ql<=m) update(ql,qr,v,lson);
		if(m<qr) update(ql,qr,v,rson);
	}
	int query(int ql,int qr,int rt,int l,int r)
	  {
		if(ql<=l&&r<=qr) return maxv[rt];
		int res=cov[rt],m=l+r>>1;
		if(ql<=m) res=max(res,query(ql,qr,lson));
		if(m<qr) res=max(res,query(ql,qr,rson));
		return res;
	  }
};
struct SegmentTree2D
{
	SegmentTree maxv[MAXN<<2],cov[MAXN<<2];
	void update(int x1,int x2,int y1,int y2,int v,int rt,int l,int r)
	  {
	  	maxv[rt].update(y1,y2,v,1,1,M);
		if(x1<=l&&r<=x2) {cov[rt].update(y1,y2,v,1,1,M); return;}
		int m=l+r>>1;
		if(x1<=m) update(x1,x2,y1,y2,v,lson);
		if(m<x2) update(x1,x2,y1,y2,v,rson);
	}
	int query(int x1,int x2,int y1,int y2,int rt,int l,int r)
	  {
	  	if(x1<=l&&r<=x2) return maxv[rt].query(y1,y2,1,1,M);
	  	int res=cov[rt].query(y1,y2,1,1,M),m=l+r>>1;
	  	if(x1<=m) res=max(res,query(x1,x2,y1,y2,lson));
		if(m<x2) res=max(res,query(x1,x2,y1,y2,rson));
		return res;
	  }
}T;
int main()
{
	scanf("%d%d%d",&N,&M,&K); ++N; ++M; N<<=1; M<<=1;
	for(int i=1;i<=K;++i)
	  {
	  	scanf("%d%d%d%d%d",&a,&b,&c,&x,&y); ++x; ++y;
	  	int used=T.query(x<<1,((x+a)<<1)-1,y<<1,((y+b)<<1)-1,1,1,N);
	  	T.update(x<<1,((x+a)<<1)-1,y<<1,((y+b)<<1)-1,used+c,1,1,N);
	  	printf("%d\n",used+c);
	  }
	return 0;
}

【二维线段树】20150209测试 千石抚子的三维积木

标签:

原文地址:http://www.cnblogs.com/autsky-jadek/p/4282929.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!