首页 > 其他分享 >CF1654G Snowy Mountain 题解

CF1654G Snowy Mountain 题解

时间:2024-01-26 17:55:51浏览次数:35  
标签:Mountain ch Snowy int 题解 st read que adj

题目链接

点击打开链接

题目解法

很牛的题

显然可以 \(O(n)\) 多源 \(bfs\) 求出 \(h_i\)

考虑从 \(st\) 开始最优的操作是什么?先延最短路径到 \(p\),然后找到 \(p\) 的相邻点 \(q\),满足 \(h_p=h_q\),在 \(p,q\) 之间横跳,耗完所有动能,然后直接滑下去(不经过高度相同的点)
为什么到 \(p\) 之前不会横跳?因为之前横跳会耗费动能,使之后能走到的点集变小,而在 \(p\) 可以横跳无数次,所有只在 \(p\) 横跳不劣(下面称 \(p\) 为平台)
考虑在 \(p\) 横跳的距离是什么?显然为 \(2h_{st}-h_p\)
我们目标是对于每个 \(st\),找到最小的 \(p\),使得能从 \(st\) 走到 \(p\)

这咋做?
考虑枚举平台 \(p\),需要求出 \(d_i\) 表示从 \(i\) 开始能到 \(p\) 的最小动能
转移显然:\(d_j+1\Rightarrow d_i(h_i=h_j),\;d_j-1\Rightarrow d_i(h_i=h_j+1)\)
但这不能直接 \(bfs\),需要钦定转移顺序
按 \(h_i\) 从小往大转移,不同层之间转移式显然的,现在需要处理的是 \(h\) 相同的点之间的转移,这可以通过树形 \(dp\) 简单求出

考虑如何优化?
考虑对于 \(h_i=h_j\) 的平台,它一定会产生 \(2\) 个长度为 \(h_i\) 的路径
考虑如何说明路径之间不交?
如果路径交,那么只有可能是包含关系,就是下面的情况(满足 \(h_i=h_j,\;h_x=h_y\)):
image
但这样就不是树了,所以不行
这样我们就得到了所有平台的 \(\sum h\) 是 \(O(n)\) 的,所以 \(h\) 的不同个数只有 \(O(\sqrt n)\) 种,对于每一种暴力做即可

时间复杂度 \(O(n\sqrt n)\)

#include <bits/stdc++.h>
#define F(i,x,y) for(int i=(x);i<=(y);i++)
#define DF(i,x,y) for(int i=(x);i>=(y);i--)
#define ms(x,y) memset(x,y,sizeof(x))
#define SZ(x) (int)x.size()-1
#define all(x) x.begin(),x.end()
#define pb push_back
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
typedef pair<int,int> pii;
template<typename T> void chkmax(T &x,T y){ x=max(x,y);}
template<typename T> void chkmin(T &x,T y){ x=min(x,y);}
inline int read(){
    int FF=0,RR=1;
    char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1;
    for(;isdigit(ch);ch=getchar()) FF=(FF<<1)+(FF<<3)+ch-48;
    return FF*RR;
}
const int N=200100,inf=1e9;
int n,h[N],ans[N],d[N];
bool vis[N];
vector<int> adj[N],buc[N],sto[N];
void dfs1(int u,int fa){
    vis[u]=true;
    for(int v:adj[u]) if(h[u]==h[v]&&v!=fa) dfs1(v,u),chkmin(d[u],d[v]+1);
}
void dfs2(int u,int fa,int D){
    chkmin(d[u],D);
    for(int v:adj[u]) if(h[u]==h[v]&&v!=fa) dfs2(v,u,d[u]+1);
}
queue<int> que;
int main(){
    n=read();
    ms(h,-1);
    F(i,1,n){ int x=read();if(x) h[i]=0,que.push(i);}
    F(i,1,n-1){ int x=read(),y=read();adj[x].pb(y),adj[y].pb(x);}
    while(!que.empty()){
        int u=que.front();que.pop();
        for(int v:adj[u]) if(h[v]==-1) h[v]=h[u]+1,que.push(v);
    }
    F(i,1,n){
        sto[h[i]].pb(i);
        bool rest=false;
        for(int j:adj[i]) if(h[i]==h[j]){ rest=true;break;}
        if(rest) buc[h[i]].pb(i);
    }
    F(i,1,n) ans[i]=h[i];
    DF(i,n,0) if(!buc[i].empty()){
        ms(d,0x3f),ms(vis,0);
        for(int st:buc[i]) d[st]=0;
        F(j,i,n){
            for(int x:sto[j]) if(!vis[x]) dfs1(x,-1),dfs2(x,-1,inf);
            for(int x:sto[j]) for(int y:adj[x]) if(j+1==h[y]) chkmin(d[y],max(0,d[x]-1));
        }
        F(j,1,n) if(!d[j]) chkmin(ans[j],i);
    }
    F(i,1,n) printf("%d ",2*h[i]-ans[i]);puts("");
    return 0;
}

标签:Mountain,ch,Snowy,int,题解,st,read,que,adj
From: https://www.cnblogs.com/Farmer-djx/p/17990357

相关文章

  • [西湖论剑 2022]web部分题解(更新中ing
    [西湖论剑2022]NodeMagicalLogin环境!启动!(ノへ ̄、)这么一看好像弱口令啊,(不过西湖论剑题目怎么会这么简单,当时真的傻),那就bp抓包试一下(这里就不展示了,因为是展示自己思路,这里就写了一下当时的NC思路,其实是不对的┭┮﹏┭┮)不是BP弱口令?那好吧,我们先看一下源码,比赛的时候是给了源......
  • Altair SimSolid常见问题解答 衡祖仿真
    Q:SimSolid究竟有什么特别之处?A:AltairSimSolid是专为设计工程师开发的结构分析软件且非常有创新性。它消除了传统FEA中特别耗时和非常专业的两项庞大任务——几何结构简化和网格划分,是一场仿真变革。简而言之,就是不用做几何简化,不用画网格,复杂装配体数量没有上限,真实三维模型直......
  • 蓝牙BQB认证申请过程常见问题解答
    BQB全名:BluetoothQualificationBody,我们一般称之为蓝牙资格认证,产品具有蓝牙功能并且在产品外观上标明蓝牙标志(Bluetoothlogo),必须通过蓝牙BQB的认证。1、为什么要过BQB?蓝牙技术联盟(BluetoothSpecialInterestGroup,简称SIG),蓝牙技术是它发明的。我们要使用它的专利,必须拿......
  • CF1515F Phoenix and Earthquake 题解
    题目链接:CF或者洛谷首先基于一个事实,答案一定是生成树,显然,每次我们都需要连边,每次都会\(-x\),那么一共会减少\((n-1)\timesx\),很显然的一个必要条件为:\[\sum_{i=1}^{n}a_i\ge(n-1)\timesx\显然一定成立。\]现在我们用来证明它同时也是一个充分条件,不妨设:\[a_1\lea......
  • latex常见问题解决
    1.Fileendedwhilescanninguseof\@writefile解决方法:删除编译文件夹内.aux扩展名结尾的文件,重新用Latex命令进行编译,自动生成正确的aux文件,完成错误的修复。注:如果还不好使,就把除.tex以外的文件均删除掉,如:.bbl,.blg,.dvi,.log等2.多行缩进ctrl+a全选后,shift+tab向前退......
  • [Bzoj 3252] 攻略 题解
    攻略题面\(n(\le2\cdot10^5)\)个点的有根树,\(k(\len)\)次从根走到叶子,每个点有权值,求经过的点的权值和的最大值.(同一个点只能算一次)Sol1我们设想一个叶子一个叶子加进去的过程。如果有两个从某个点到叶子的路径,我们可以如图把他分成两条路径。那么他满足贪心,也就是每次......
  • P4159 [SCOI2009] 迷路 题解
    P4159[SCOI2009]迷路搬运工题目链接首先我们先考虑这道题的弱化版如何处理。假如所有的边权都是零和一。这时他们的边权可以看做这两个点走一步到达之间的方案数。而对于走t步,我们可以推出下列式子,\(f_{i,j}\)表示从节点\(i\)到节点\(j\)的方案数。\[f_{i,j}=\su......
  • # python3 安装Crypto包 出现No module named ‘Crypto‘和No module named ‘Crypto.
    python3安装Crypto包出现Nomodulenamed‘Crypto‘和Nomodulenamed‘Crypto.Util‘问题解决方法1.改成安装pycryptodome然而在python36中无法报错:error:MicrosoftVisualC++14.0orgreaterisrequired"2.改用Anaconda安装指定版本的pycryptodomepipins......
  • 2024年1月Java项目开发指南12:前后端分离项目跨域问题解决
    创建config文件夹,创建WebConfig文件代码如下(可以直接抄)packagecc.xrilang.serversystem.config;importorg.springframework.context.annotation.Configuration;importorg.springframework.web.servlet.config.annotation.CorsRegistry;importorg.springframework.web.se......
  • CF145E Lucky Queries 题解
    题目链接:CF或者洛谷前置知识点:序列操作本文关键词约定俗称:因为频繁敲最长不下降子序列\(LNCS\)和最长不上升子序列\(LNIS\)太麻烦了,下文将\(000011111\)这种最长不降子序列用\(LIS\)描述,\(1111100000\)这种最长不升子序列用\(LDS\)描述。这里面只有\(4\)和\(7......