Scaffolding

这篇博客探讨了一种使用Treap数据结构解决在有限材料情况下搭建多层建筑的最小运输次数优化问题。文章详细介绍了如何通过广义笛卡尔树的优化方法,将问题转化为Treap的构造和动态规划转移,最终实现线性时间复杂度的解决方案。
摘要由CSDN通过智能技术生成

Scaffolding

题解

考虑我们怎样放才是最优的放法。
很明显,当我们上楼后是不能带着材料下来的,所以我们带上楼的材料最多也只是刚好够放完上面一层,剩下的材料我们都在下一层中分完后再拿到上面去。
但我们该怎么分层呢?
很明显,对于一个完整的矩形我们是可以将它完整地分为一层的,我们对于这种完整的矩形我们在哪个位置上楼并不会影响我们的答案。
所以,我们要做的是将这样的柱状图分为多个完整的矩形处理。
观察到 n ⩽ 1 0 5 n\leqslant 10^5 n105,广义笛卡尔树的 O ( n 2 ) O\left(n^2\right) O(n2)暴力建图是明显不行的,考虑用 t r e a p treap treap的方法建图,这部分是 O ( n ) O\left(n\right) O(n)的。

在建图的同时,我们可以在树上进行 d p dp dp转移。
由于我们建完上面的楼后可能会剩一部分材料,而这部分材料只能拿到下面一层,所以我们肯定是从从叶子往根 d p dp dp,某个节点有多的材料,人给它父亲。
我们记节点 i i i代表的矩阵的大小为 s u m i sum_{i} sumi t o t i tot_{i} toti表示 i i i的子树的总矩阵大小, f i f_{i} fi表示建完点 i i i的子树需要的最少运送次数, g i g_{i} gi表示建完 i i i的子树可以给它的祖先节点留下多少材料。
容易得到 d p dp dp转移式:
f u = ∑ v ∈ s o n u f v + max ⁡ ( 0 , ⌈ s u m u − ∑ v ∈ s o n u g v m ⌉ ) f_{u}=\sum_{v\in son_{u}}f_{v}+\max(0,\left\lceil\frac{sum_{u}-\sum_{v\in son_{u}}g_{v}}{m}\right\rceil) fu=vsonufv+max(0,msumuvsonugv)
g u = m f u − t o t u g_{u}=mf_{u}-tot_{u} gu=mfutotu
这些转移都可以在遍历整棵树时进行,树在我们输入的时候就可以建好了。

时间复杂度 O ( n ) O\left(n\right) O(n)

源码

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 100005
#define lowbit(x) (x&-x)
#define reg register
#define pb push_back
#define mkpr make_pair
#define fir first
#define sec second
typedef long long LL;
#define int LL
typedef unsigned long long uLL;
const int INF=0x3f3f3f3f;
const int mo=1e9+7;
const int inv2=499122177;
const int jzm=2333;
const int zero=10000;
const int lim=30000;
const int orG=3,invG=332748118;
const double Pi=acos(-1.0);
const double eps=1e-5;
typedef pair<int,int> pii;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
	_T f=1;x=0;char s=getchar();
	while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
	while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
	x*=f;
}
template<typename _T>
void print(_T x){if(x<0){x=(~x)+1;putchar('-');}if(x>9)print(x/10);putchar(x%10+'0');}
LL gcd(LL a,LL b){return !b?a:gcd(b,a%b);}
int add(int x,int y,int p){return x+y<p?x+y:x+y-p;}
void Add(int &x,int y,int p){x=add(x,y,p);}
int qkpow(int a,int s,int p){int t=1;while(s){if(s&1LL)t=1ll*a*t%p;a=1ll*a*a%p;s>>=1LL;}return t;}
int n,m,h[MAXN],lson[MAXN],rson[MAXN],sta[MAXN],siz[MAXN],stak;
LL f[MAXN],g[MAXN],sum[MAXN];
void sakura(int rt,int minn){
	int sumg=0;siz[rt]++;
	if(lson[rt])sakura(lson[rt],h[rt]),siz[rt]+=siz[lson[rt]],
		f[rt]+=f[lson[rt]],sumg+=g[lson[rt]],sum[rt]+=sum[lson[rt]];
	if(rson[rt])sakura(rson[rt],h[rt]),siz[rt]+=siz[rson[rt]],
		f[rt]+=f[rson[rt]],sumg+=g[rson[rt]],sum[rt]+=sum[rson[rt]];
	int tmp=siz[rt]*(h[rt]-minn)-sumg;sum[rt]+=(h[rt]-minn)*siz[rt]; 
	if(tmp>0)f[rt]+=(tmp+m-1LL)/m;
	g[rt]=1ll*m*f[rt]-sum[rt];
}
signed main(){
	while(scanf("%lld %lld",&n,&m)!=EOF){
		for(int i=1;i<=n;i++){
			read(h[i]);bool flag=0;
			while(stak&&h[sta[stak]]>h[i])stak--,flag=1;
			if(sta[stak])lson[sta[stak]]=i;
			if(flag)rson[i]=sta[stak+1];sta[++stak]=i;
		}
		sakura(sta[1],0);
		printf("%lld\n",f[sta[1]]);stak=0;
		for(int i=1;i<=n;i++)lson[i]=siz[i]=rson[i]=f[i]=g[i]=sum[i]=0;
	}
	return 0;
}

谢谢!!!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 这个错误是因为你要在一个非空的目录中进行项目脚手架构建,你可以在一个新的空目录中进行构建或者删除现有的目录中的所有内容再进行构建。如果你确定不需要目录中的任何内容,可以使用以下命令强制删除目录(请小心使用): ``` rm -rf C:\Users\张永军\Desktop\Vue3+ts+project\app_demo ``` 然后再重新运行你的命令即可。 ### 回答2: npx是Node.js的一个包执行工具,用于执行安装在全局命令下的包,也可以直接执行本地项目下的包。在这个问题中,npx执行了一个名为7的包,并且安装成功,用时1.65秒。接着在C:\Users\张永军\Desktop\Vue3 ts project\app_demo路径下,进行了一个项目脚手架的搭建。然而,出现了一个错误:目标目录不为空。 这个错误的原因是在搭建项目时,目标目录(即C:\Users\张永军\Desktop\Vue3 ts project\app_demo)不为空。可能是在该目录下已经存在一些文件或文件夹,导致无法将项目脚手架生成到该目录下。 要解决这个错误,可以按照以下步骤操作: 1. 打开目标目录(C:\Users\张永军\Desktop\Vue3 ts project\app_demo),确认其中的文件和文件夹。 2. 如果目标目录中存在不重要的文件或文件夹,可以将其移动到其他位置,或者直接删除。 3. 如果目标目录中存在重要的文件或文件夹,请备份它们,然后将其移动到其他位置,以便后续可以还原。 4. 确保目标目录为空后,再次执行Scaffolding project的命令。 通过以上步骤,您应该能够成功搭建项目脚手架,并在目标目录下生成所需的文件和文件夹。 ### 回答3: 根据给出的信息来看,使用npx命令成功安装了一个项目,并耗时1.65秒。这个项目的路径是C:\Users\张永军\Desktop\Vue3 ts project\app_demo。 然而,安装的过程中遇到了一个错误。错误提示说目标目录不为空。这意味着在安装项目之前,目标目录C:\Users\张永军\Desktop\Vue3 ts project\app_demo已经存在一些文件或文件夹。 通常,在使用npx安装项目时,要求目标目录是一个空目录,这样可以避免覆盖或混淆已存在的文件。因此,需要将目标目录清空或选择一个空的目录来安装这个项目。 在处理这个错误时,可以尝试以下几个步骤: 1. 打开目标目录C:\Users\张永军\Desktop\Vue3 ts project\app_demo,检查该目录中的文件和文件夹。 2. 如果目录中有其他文件或文件夹,可以将其备份到其他地方或删除,以确保目录是空的。 3. 重新运行npx命令,安装项目到目标目录。 如果按照上述步骤清空目标目录后,问题仍然存在,可能需要检查npx命令的版本和相关依赖项是否正确安装。同时,还可以尝试在命令行中使用其他参数或选项来更好地处理目标目录不为空的情况。 总之,根据给出的信息,安装项目时遇到了目标目录不为空的错误。需要清空目标目录或选择一个空的目录来安装项目,并检查其他可能的问题来解决这个错误。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值