UVA437 巴比伦塔 The Tower of Babylon 题解

这题其实有 \(O(n \log n)\)? 的做法。

首先,如果一个砖块可以压在另一个砖块上面只要满足长边比另一个砖块的长边小,短边也比另一个砖块的短边小,这是非常显然的。写成式子:如果这个砖块宽和长分别为 \(kx,ky(kx<ky)\)?,另一个砖块宽和长分别为 \(tx,ty(tx<ty)\)?,若满足 \(kx<tx,ky<ty\)? 则可以放。

这就非常像二维数点,于是我们保证好长宽的大小关系,离散化一下,直接用树状数组二维数点即可。

#include<bits/stdc++.h>
#define log(a) cerr<<"\033[32m[DEBUG] "<<#a<<‘=‘<<(a)<<" @ line "<<__LINE__<<"\033[0m"<<endl
#define LL long long
#define SZ(x) ((int)x.size()-1)
#define ms(a,b) memset(a,b,sizeof a)
#define F(i,a,b) for(int i=(a);i<=(b);++i)
#define DF(i,a,b) for(int i=(a);i>=(b);--i)
using namespace std;
inline int read(){char ch=getchar(); int w=1,c=0;
	for(;!isdigit(ch);ch=getchar()) if (ch==‘-‘) w=-1;
	for(;isdigit(ch);ch=getchar()) c=(c<<1)+(c<<3)+(ch^48);
	return w*c;
}
const int N=110;
int cnt,tot,s[N],x[N],y[N],z[N];
namespace BIT{
 	LL maxn[N];
 	void add(int x,LL y){for(;x<=tot;x+=x&-x)maxn[x]=max(maxn[x],y);}
 	LL qry(int x){LL s=0;for(;x;x-=x&-x)s=max(s,maxn[x]);return s;}
}
using namespace BIT;
vector<pair<int,int> >v[N];
LL f[N],ans;
signed main(){
	int n=read();
	for(;n;n=read()){
		ans=0;tot=0;
		F(i,1,n){
			x[i]=read(),y[i]=read(),z[i]=read();
			s[++tot]=x[i];
			s[++tot]=y[i];
			s[++tot]=z[i];
		}sort(s+1,s+tot+1);
		tot=unique(s+1,s+tot+1)-s-1;
		F(i,1,tot)maxn[i]=0,v[i].clear();
		F(i,1,n){
			x[i]=lower_bound(s+1,s+tot+1,x[i])-s;
			y[i]=lower_bound(s+1,s+tot+1,y[i])-s;
			z[i]=lower_bound(s+1,s+tot+1,z[i])-s;
			if(x[i]>y[i])swap(x[i],y[i]);
			if(x[i]>z[i])swap(x[i],z[i]);
			if(y[i]>z[i])swap(y[i],z[i]);
			v[y[i]].emplace_back(x[i],z[i]);
			v[z[i]].emplace_back(x[i],y[i]);
			v[z[i]].emplace_back(y[i],x[i]);
		}
		F(i,1,tot){
			queue<LL>q;
			for(auto[j,k]:v[i])q.push(qry(j-1)+s[k]);
			for(auto[j,k]:v[i]){
				LL x=q.front();q.pop();
				ans=max(ans,x);
				add(j,x);
			}
		}printf("Case %d: maximum height = %lld\n",++cnt,ans);
	}
	return 0;
}

UVA437 巴比伦塔 The Tower of Babylon 题解

上一篇:本地生活综合性需求图谱的构建及应用


下一篇:检测设备跳转