题目传送门

思路

放眼整个题解区没有我这种解法,因此来写一篇题解。

既然要求我们选择一个节点作为根,那么我们就枚举根。

接下来的问题就是如何 \(\mathcal{O}(1)\) 或 \(\mathcal O(\log n)\) 计算贡献。

我们可以把节点分为四类:这个节点,这个节点的父亲,这个节点的儿子,另外的节点。

其中第 \(1/2\) 类非常容易解决。难解决的就是这个节点的儿子和另外的节点。

不妨考虑线段树,把这个节点所有的儿子压到一个区间内,为此,我们需要寻找一种新的编号方式。

原本正常把树拍扁都是根据 \(\mathcal DFS\) 序遍历的,现在我们需要以 \(\mathcal BFS\) 序遍历,而且以点 \(i\) 为根时,它原本的父亲 \(fa_i\) 也会变成它的儿子。

于是如此模拟即可。

代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
int const N=1e6+10;
int n,go[N];
struct node{int w,id;}a[N];
int vis[N],fa[N],minx[N],maxx[N],c[N];
vector<int>b[N];
struct Segment_Tree{
#define ls (x<<1)
#define rs (x<<1|1)
#define mid ((l+r)>>1)
int c[N<<2];
inline void build(int x,int l,int r){
if (l==r){c[x]=a[l].w;return;}
build(ls,l,mid);build(rs,mid+1,r);
c[x]=max(c[ls],c[rs]);
}
inline void update(int x,int l,int r,int p,int v){
if (l==r){c[x]=v;return;}
if (p<=mid) update(ls,l,mid,p,v);
else update(rs,mid+1,r,p,v);
c[x]=max(c[ls],c[rs]);
}
inline int query(int x,int l,int r,int ll,int rr){
if (ll<=l && r<=rr) return c[x];
int res=-2e9;
if (ll<=mid) res=max(res,query(ls,l,mid,ll,rr));
if (mid<rr) res=max(res,query(rs,mid+1,r,ll,rr));
return res;
}
}T;
inline bool cmp(node x,node y){return x.id<y.id;}
inline int solve(int x){
int la=0;
if (fa[x]) la=c[fa[x]],T.update(1,1,n,go[fa[x]],-2e9);
T.update(1,1,n,go[x],-2e9);
int res=c[x];
if (minx[x]<=maxx[x]) res=max(res,T.query(1,1,n,minx[x],maxx[x])+1);
if (minx[x]-1>=1) res=max(res,T.query(1,1,n,1,minx[x]-1)+2);
if (maxx[x]+1<=n) res=max(res,T.query(1,1,n,maxx[x]+1,n)+2);
if (fa[x]) res=max(res,la+1),T.update(1,1,n,go[fa[x]],la);
T.update(1,1,n,go[x],c[x]);
return res;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>n;
for (int i=1;i<=n;++i) cin>>a[i].w,c[i]=a[i].w;
queue<int>q;
for (int i=1;i<n;++i){
int u,v;cin>>u>>v;
b[u].push_back(v);
b[v].push_back(u);
}
q.push(1);vis[1]=1;a[1].id=1;
int cnt=1;
while (!q.empty()){
int x=q.front();q.pop();
minx[x]=cnt+1;vis[x]=1;
for (auto v:b[x]){
if (vis[v]) continue;
fa[v]=x;
a[v].id=++cnt;q.push(v);
}
maxx[x]=cnt;
}
for (int i=1;i<=n;++i) go[i]=a[i].id;
sort(a+1,a+n+1,cmp);
T.build(1,1,n);
int ans=9e18;
for (int i=1;i<=n;++i) ans=min(ans,solve(i));
cout<<ans<<'\n';
return 0;
}

CF796C Bank Hacking的更多相关文章

  1. CF796C Bank Hacking 思维

    Although Inzane successfully found his beloved bone, Zane, his owner, has yet to return. To search f ...

  2. CF796C Bank Hacking 题解

    洛谷链接 题目 Although Inzane successfully found his beloved bone, Zane, his owner, has yet to return. To ...

  3. CF796C Bank Hacking 细节

    思路十分简单,答案只有 3 种可能,但是有一些细节需要额外注意一下. code: #include <bits/stdc++.h> #define N 300002 #define set ...

  4. C. Bank Hacking 解析(思維)

    Codeforce 796 C. Bank Hacking 解析(思維) 今天我們來看看CF796C 題目連結 題目 略,請直接看原題. 前言 @copyright petjelinux 版權所有 觀 ...

  5. Code Forces 796C Bank Hacking(贪心)

    Code Forces 796C Bank Hacking 题目大意 给一棵树,有\(n\)个点,\(n-1\)条边,现在让你决策出一个点作为起点,去掉这个点,然后这个点连接的所有点权值+=1,然后再 ...

  6. codeforce 796C - Bank Hacking(无根树+思维)

    题目 Although Inzane successfully found his beloved bone, Zane, his owner, has yet to return. To searc ...

  7. CodeForces - 796C Bank Hacking

    思路:共有n-1条边连接n个点,即形成一棵树.一开始需要选择一个点hack--将这个点视为根结点,与它相邻的点防御值加1,与它相隔一个在线点的点的防御也加1.当根节点被hack,即这个点被删除,又变成 ...

  8. Codeforces Round #408 (Div. 2) C. Bank Hacking

    http://codeforces.com/contest/796/problem/C Although Inzane successfully found his beloved bone, Zan ...

  9. Codeforces Round #408 (Div. 2)C. Bank Hacking(STL)

    题目链接:http://codeforces.com/problemset/problem/796/C 题目大意:有n家银行,第一次可以攻击任意一家银行(能量低于自身),跟被攻击银行相邻或者间接相邻( ...

  10. Codeforces Round #408 (Div. 2) C.Bank Hacking(二分)

    传送门 题意 给出n个银行,银行之间总共有n-1条边,定义i与j有边相连为neighboring,i到j,j到k有边,则定义i到k的关系为semi- neighboring, 每家银行hack的难度为 ...

随机推荐

  1. <七>理解多态

    理解多态 多种多样的形态(静态多态,动态多态) 静态多态(编译时期) 1:函数重载 bool comparet(int ,int); bool compare(double,double); comp ...

  2. EASE-Grid经纬度与行列号转换公式 以 25KM的HDF数据为例

    /// <summary> /// 把经纬度转换成行列号 /// </summary> /// <param name="pLng"></ ...

  3. 通过 CancellationToken 提高 Web 性能

    在 Web 开发中,经常会遇到这样的场景:用户发起一个请求,Web 服务器执行一些计算密集型的操作,等待结果返回给用户.这种情况下,如果用户在等待结果的过程中取消了请求,那么服务器端依然会继续执行计算 ...

  4. texlive安装与vscode环境配置

    环境 系统:windows10 texlive下载 下载地址: 官网:http://tug.org/texlive/ 清华镜像源: https://mirrors.tuna.tsinghua.edu. ...

  5. 基于 Traefik 如何实现 path 末尾自动加斜杠?

    前言 Traefik 是一个现代的 HTTP 反向代理和负载均衡器,使部署微服务变得容易. Traefik 可以与现有的多种基础设施组件(Docker.Swarm 模式.Kubernetes.Mara ...

  6. 3D视觉算法初学概述

    背景知识 RGB-D相机 一,基于3DMM的三维人脸重建技术概述 1.1,3D 人脸重建概述 1.2,初版 3DMM 二,视觉SLAM算法基础概述 2.1,视觉里程计 2.2,后端优化 2.3,回环检 ...

  7. [数据与分析可视化] D3入门教程1-d3基础知识

    d3.js入门教程1-d3基础知识 文章目录 d3.js入门教程1-d3基础知识 1 HTML介绍 1.1 什么是HTML? 1.2 自定义文档样式CSS 1.3 构建svg图形 2 d3绘图入门 2 ...

  8. [Untiy]贪吃蛇大作战(一)——开始界面

    前言: 刚学unity没多久吧(大概1个月多点),这是我自己做的除官网之外的第一个游戏demo,中间存在很多不足的地方,但是还是希望可以给需要的人提供一些思路和帮助,有问题的小伙伴可以找我一起探讨一起 ...

  9. MySQL 索引的创建、删除

    MySQL中索引的创建有三种方法,索引的删除有两种方法. 一.创建索引 (1)使用create index # 1.创建普通索引 create index 索引名 on 表名 (列名[(限制索引长度) ...

  10. 轻松理解Promise.all 、Promise.then、Promise.race有什么区别以及使用方法

    简单来说呢,Promse.all一般应用于某个场景需要多个接口数据合并起来才能实现 有个极大地好处我必须说一下,请求顺序和获取数据顺序是一样的哟,大可放心使用~~ const success1 = n ...