3. 千石抚子的三维积木(nadeko.cpp/in/out) 3.5s 512MB 10*10=100分
p.s.本题含有一些(本人)黑历史,请自动过滤题目背景…= =
自从蛇切绳被搞掉之后,抚子认识到普通的蛇其实是很和谐的东西。于是她开始养蛇,有天在家无聊就开始用蛇堆积木。由于她是驯蛇高手所以它们都很听话堆上去之后就不会动,并且每条蛇可以被视为一块长方体(这个比喻有点。。好吧,接下来都把蛇叫做积木了)。
堆积木是在一块W*D的平地上进行的,每堆一个积木时会告诉你它的长宽高和放置的左上角x,y坐标。
它的下底面高度等于在它没加进来之前,它所占的平面中最高的积木高度(就像三维俄罗斯方块)。
抚子想知道加入每块积木之后这块积木上底面的高度。
输入格式:
第一行三个数W,D,n,W为场地的长,D为宽,n为积木数
接下来n行,每行5个数a,b,c,x,y,分别表示长宽高和放置的左上角x,y坐标(注意左上角指的是平面中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)
在一维情况下,跟wc2012的memory的某个过程差不多。
就是要你实现两个操作,一是询问一段中最大值,二是把一段的每个元素与某个值取max。
我们可以对每个线段树节点维护两个值:quan和bu,quan表示把这个区间全部覆盖的最大值,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; }