首页 > 其他分享 >笛卡尔树Kattis-Scaffolding

笛卡尔树Kattis-Scaffolding

时间:2023-05-09 22:57:52浏览次数:44  
标签:Scaffolding Kattis 笛卡尔 int long sons dfs 100010

笛卡尔树Kattis-Scaffolding

注释已经写在代码里了,注意下建树就行

#include<bits/stdc++.h>
/*先对题意进行分析,每次带m根柱子,进行x轮,每次往左/右/上搭建,问x的最小值?
一开始在想,怎么就会有最小值呢?后来发现题目说不能往下走
我们还是把图看成一棵树
就是说你可以向两个子节点去走,然后花费siz的木条把这个树填满,然后继续选择......
贪心的思想的话,我每一次爬树爬到某个点,材料用完最好(有剩余的话就浪费了,不如去填充其他的?)
也就是说我这一排,能放就放
但是我觉得dp更加稳妥,不知道贪心是不是对的
转移方程呢?
首先应该不是背包问题,因为我求的是轮数,没有“占用空间”这一回事
而且我用贪心,尽力填充下层,所以不存在背包问题
那就是简单的dp了
ans=f[i],表示建设到以根i为子树需要的轮
但我肯定要知道还剩了多上根柱子建造后面的啊
g[i]带了f[i]轮竹子,当前区间高度达到h[i]后剩多少竹子来搭更父亲节点部分的竹子。
*/

#define int long long
using namespace std;
int n,m,rt;
int head,tail;
int a[100100],sons[100010][2],q[100010];
int l[100010],r[100010];
long long f[100010],g[100010];
inline void dfs(int x,int fa){
    l[x]=r[x]=x;
	if(sons[x][0]){
		dfs(sons[x][0],x);
		f[x]+=f[sons[x][0]];
		g[x]+=g[sons[x][0]];
		l[x]=l[sons[x][0]];
	}
	if(sons[x][1]){
		dfs(sons[x][1],x);
		f[x]+=f[sons[x][1]];
		g[x]+=g[sons[x][1]];
		r[x]=r[sons[x][1]];
	}
	long long used=1ll*(r[x]-l[x]+1)*(a[x]-a[fa])-g[x];
	if(used<0){//剩余柱子
        g[x]=-used;
	}
	else{//往上攀升
		long long d=used/m;
		if(used%m!=0){
            d++;
		}//注意这里是要用完的,轮数要++
		f[x]+=d;
		g[x]=d*m-used;
	}
}
inline int read(){
    int x=0,f=1;
    char sons=getchar();
    while(sons<'0'||sons>'9')
    {
        if(sons=='-')
            f=-1;
        sons=getchar();
    }
    while(sons>='0' && sons<='9')
        x=x*10+sons-'0',sons=getchar();
    return x*f;
}
signed main() {

    n=read();
    m=read();
    rt=1,head=1,tail=0;
    for(int i=1;i<=n;i++){
    	a[i]=read();
	}
	memset(sons,0,sizeof(sons));//不用也可以
    for(int i=1;i<=n;i++) {
        int res=-1;
        while(head<=tail&&a[i]<=a[q[tail]]){
            res=q[tail--];
        }
        if(res!=-1) {
            if(rt==res)rt=i;
            sons[i][0]=res;
        }
        if(head<=tail)sons[q[tail]][1]=i;
        q[++tail]=i;
    }//正常建树
    l[rt]=1;
    r[rt]=n;
    dfs(rt,0);
   // for(int i=1;i<=n;i++){
        //cout<<l[i]<<" "<<r[i]<<endl;
   // }
    cout<<f[rt];
}

标签:Scaffolding,Kattis,笛卡尔,int,long,sons,dfs,100010
From: https://www.cnblogs.com/linghusama/p/17386591.html

相关文章

  • 笛卡尔树
    性质其节点具有\(2\)个权值,分别是\((key,val)\),以\(key\)看,其为一颗二叉搜索树,以\(val\)看,其为一个堆(定义)。二叉搜索树:左子树如果不空,则其权值一定小于根节点;右子树如果不空,则其权值一定大于根节点。堆:完全二叉树,每个节点的值大于等于(或小于等于)其子树中的每个节......
  • @黎耀天 发扬 笛卡尔, @物空必能 发扬 牛顿, 无敌了 。
    @黎耀天发扬笛卡尔, @物空必能发扬牛顿,  @joywee2007 发扬爱因斯坦和老子,  无敌了 。 这篇文章的灵感来自 昨前天 看到 @物空必能在牛顿吧发的 《物质的弹性与屈服强度——力学就应当探究力的问题》    https://tieba.baidu.com/p/83932......
  • C++ 树进阶系列之笛卡尔树的两面性
    1.前言笛卡尔树是一种特殊的二叉树数据结构,融合了二叉堆和二叉搜索树两大特性。笛卡尔树可以把数列(组)对象映射成二叉树,便于使用笛卡尔树结构的逻辑求解数列的区间最值或......
  • 笛卡尔树~cartesian-tree
    笛卡尔树简介笛卡尔树是一种平衡树,它的结构和treap相同,但是由于它能在O(n)时间构造,同时具有一些很有意思的性质。构造笛卡尔树的节点由键值对\((k,w)\)组成。其中键......
  • 笛卡尔树
    笛卡尔树总述笛卡尔树是一种二叉树,每一个结点由一个键值二元组\((k,w)\)构成。要求\(k\)满足二叉搜索树的性质,而\(w\)满足堆的性质,如果笛卡尔树的\(k,w\)键值确......
  • 动态笛卡尔树
    这里讲的动态笛卡尔树的问题指的是你要对一个序列单点加值并维护笛卡尔树的形态信息。由于具有严格偏序关系的数列对应的笛卡尔树唯一,我们只需要像维护Treap一样单点上......
  • 【YBT2023寒假Day12 B】仰望星空(DP)(线段树)(笛卡尔树)
    仰望星空题目链接:YBT2023寒假Day12B题目大意有一个n*n的网格,第i列下面的ai个点都是障碍。然后又一些不是障碍的地方有特殊点,删掉它有费用。要你用最小费用使得......
  • 为笛卡尔积运算而生的Reduce(Excel函数集团)
    我要是没记错,Reduce这词是减少的意思,可是当他作为Excel函数出现时,我真没看出哪里Reduce了……好吧,其实可以换种理解,缩减了嵌套(帮助里写的是“将数组缩减为累计值)。来来来......
  • left join(左连接)、right join(右连接)、full join(全连接)、inner join(内连接)、cr
    (1)leftjoin(左连接)在两张表进行连接查询时,会返回左表所有的行数据,右表中返回只返回和左表匹配的数据,没有的显示为Null。(2)rightjoin(右连接)在两张表进行连接查询时,会返......
  • 笛卡尔树学习笔记
    笛卡尔树下文的资料多摘自OIWiki性质笛卡尔树是一种二叉树,每一个节点都由一个键值二元组\((k,w)\)构成。要求\(k\)满足二叉搜索树的性质,而\(w\)满足堆的性质。如......