zoukankan      html  css  js  c++  java
  • 【二维线段树】20150209测试 千石抚子的三维积木

    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
    ",used+c);
    	  }
    	return 0;
    }
  • 相关阅读:
    有关base64编码算法的相关操作
    不宜多吃的十种垃圾食品
    ~ 無 淚 的 天 使 ~
    Datagrid 中添加ComboBox 的两种方法(winform)
    刀兄写的IIS管理类(C#)
    17种常用正则表达式
    正则表达式经典 (转)
    C#中Pinvoke的使用
    C#中Pinvoke的使用2
    异步操作样本
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/4282929.html
Copyright © 2011-2022 走看看