“科大讯飞杯”第18届上海大学程序设计联赛春季赛暨高校网络友谊赛 G 血压游戏
[血压游戏] (https://ac.nowcoder.com/acm/contest/5278/G)
神奇的tag数组...,巧妙弥补了高度损失。
方法一:dsu on tree
类似长链剖分,不过是用unordered_map 来维护高度相关信息,swap复杂度是O(1)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
#define dbg(x...) do { cout << "\033[32;1m" << #x <<" -> "; err(x); } while (0)
void err() { cout << "\033[39;0m" << endl; }
template<class T, class... Ts> void err(const T& arg,const Ts&... args) { cout << arg << " "; err(args...); }
const int N = 200000 + 5;
int head[N], ver[N<<1], nxt[N<<1], tot;
int dep[N];
int n, rt;
ll a[N], tag[N];
unordered_map<int, ll> mp[N];
void add(int x, int y){
ver[++tot] = y, nxt[tot] = head[x], head[x] = tot;
}
void ins(int x, int d, ll cnt){
if(!mp[x].count(d)){
mp[x][d] = cnt + tag[x]; // x 下面的边数
} else {
mp[x][d] = max(mp[x][d] - tag[x], 1ll) + cnt + tag[x];
}
}
void merge(int x, int y){
if(mp[x].size() < mp[y].size()){
swap(mp[x], mp[y]);
swap(tag[x], tag[y]);
}
for(auto t : mp[y]){
if(t.second){
ins(x, t.first, max(t.second - tag[y], 1ll));
}
}
}
void dfs(int x, int fa){
dep[x] = dep[fa] + 1;
for(int i=head[x];i;i=nxt[i]){
int y = ver[i];
if(y == fa) continue;
dfs(y, x);
merge(x, y);
}
if(a[x])
ins(x, dep[x], a[x]);
tag[x] ++;
}
int main(){
scanf("%d%d", &n, &rt);
for(int i=1;i<=n;i++){
scanf("%lld", &a[i]);
}
for(int i=1;i<n;i++){
int x, y;scanf("%d%d", &x, &y);
add(x, y);add(y, x);
}
dfs(rt, 0);
ll res = 0;
for(auto t : mp[rt]){
if(t.second) res += max(1ll, t.second - tag[rt]);
}
cout << res << endl;
return 0;
}
方法二:
按照深度分组,建立虚树,然后树形DP求解即可
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
#define dbg(x...) do { cout << "\033[32;1m" << #x <<" -> "; err(x); } while (0)
void err() { cout << "\033[39;0m" << endl; }
template<class T, class... Ts> void err(const T& arg,const Ts&... args) { cout << arg << " "; err(args...); }
const int N = 200000 + 5;
const int M = 2*N;
int head[N], ver[M], nxt[M];
int dfn[N], rnk[N], cnt;
int dep[N], f[N][20];
int st[N], top, inq[N];
ll a[N];
int n, rt, tot;
vector<int> node[N];
struct Graph{
int head[N], ver[M], nxt[M], tot;
void add(int x, int y){
ver[++tot] = y, nxt[tot] = head[x], head[x] = tot;
}
}G;
void add(int x, int y){
ver[++tot] = y, nxt[tot] = head[x], head[x] = tot;
}
void dfs(int x, int fa){
dfn[x] = ++cnt, rnk[cnt] = x;
for(int i=head[x];i;i=nxt[i]){
if(ver[i] == fa) continue;
f[ver[i]][0] = x;
dep[ver[i]] = dep[x] + 1;
dfs(ver[i], x);
}
}
int lca(int x, int y){
if(dep[x] > dep[y]) swap(x, y);
for(int i=19;i>=0;i--) if(dep[f[y][i]] >= dep[x]) y = f[y][i];
if(x == y) return x;
for(int i=19;i>=0;i--) if(f[y][i] != f[x][i]) y = f[y][i], x = f[x][i];
return f[x][0];
}
void insert(int x){
if(x == rt) return;
int t = lca(x, st[top]);
if(t != st[top]){
while(top > 1 && dfn[st[top-1]] > dfn[t]){
G.add(st[top-1], st[top]);
top --;
}
if(dfn[t] > dfn[st[top-1]]){
G.head[t] = 0;
G.add(t, st[top]);
st[top] = t;
} else {
G.add(t, st[top--]);
}
}
G.head[x] = 0, st[++top] = x;
}
ll dfs(int x){
if(inq[x]) return a[x];
ll res = 0;
for(int i=G.head[x];i;i=G.nxt[i]){
int y = G.ver[i];
ll val = dfs(y);
if(val) // 没有就不要加
res += max(val - dep[y] + dep[x], 1ll);
}
return res;
}
ll get(int x){
if(!node[x].size()) return 0;
sort(node[x].begin(), node[x].end(),[=](int a, int b){return dfn[a] < dfn[b];});
st[top = 1] = rt; G.tot = 0; G.head[rt] = 0;
for(auto t : node[x]) insert(t), inq[t] = 1;
for(int i=1;i<top;i++){
G.add(st[i], st[i+1]);
}
ll res = dfs(rt);
if(res >= 2) res --;
for(auto t : node[x]) inq[t] = 0;
return res;
}
int main(){
scanf("%d%d", &n, &rt);
for(int i=1;i<=n;i++){
scanf("%lld", &a[i]);
}
for(int i=1;i<n;i++){
int x, y;scanf("%d%d", &x, &y);
add(x, y);
add(y, x);
}
dep[rt] = 1;
dfs(rt, 0);
for(int i=1;i<=n;i++){
node[dep[i]].push_back(i);
}
for(int j=1;j<20;j++){
for(int i=1;i<=n;i++){
f[i][j] = f[f[i][j-1]][j-1];
}
}
ll res = 0;
for(int i=1;i<=n;i++){
res += get(i);
}
cout << res <<endl;
return 0;
}
“科大讯飞杯”第18届上海大学程序设计联赛春季赛暨高校网络友谊赛 G 血压游戏的更多相关文章
- “盛大游戏杯”第15届上海大学程序设计联赛夏季赛暨上海高校金马五校赛题解&&源码【A,水,B,水,C,水,D,快速幂,E,优先队列,F,暴力,G,贪心+排序,H,STL乱搞,I,尼姆博弈,J,差分dp,K,二分+排序,L,矩阵快速幂,M,线段树区间更新+Lazy思想,N,超级快速幂+扩展欧里几德,O,BFS】
黑白图像直方图 发布时间: 2017年7月9日 18:30 最后更新: 2017年7月10日 21:08 时间限制: 1000ms 内存限制: 128M 描述 在一个矩形的灰度图像上,每个 ...
- 埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛 C序列变换
链接:https://www.nowcoder.com/acm/contest/91/C来源:牛客网没有账号的同学这样注册,支持博主 题目描述 给定两个长度为n的序列,ai, bi(1<=i&l ...
- K-序列(埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛)
题目描述 给一个数组 a,长度为 n,若某个子序列中的和为 K 的倍数,那么这个序列被称为“K 序列”.现在要你 对数组 a 求出最长的子序列的长度,满足这个序列是 K 序列. 输入描述: 第一行为 ...
- SHU 第15届上海大学程序设计联赛夏季赛[热身赛] 第三题(G题) - 英语成绩
看完题目就觉得是个图论题…… 每个人的成绩就是vertice,两个人的分数差就是edge,那么肯定类似于一种relax的方式,不断将每个人的成绩的min往上提, 当然,单纯的遍历一遍G.E肯定不可能就 ...
- “新智认知”杯上海高校程序设计竞赛暨第十七届上海大学程序设计春季联赛(D题,贪心+栈)
链接:https://ac.nowcoder.com/acm/contest/551/D来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 524288K,其他语言10485 ...
- H、CSL 的拼图 【多维点的交换】 (“新智认知”杯上海高校程序设计竞赛暨第十七届上海大学程序设计春季联赛)
题目传送门:https://ac.nowcoder.com/acm/contest/551/H 题目描述 众所周知 CSL 不仅玩魔方很强,打麻将也很强.今天他打魔法麻将的时候,在路上撞到了一个被打乱 ...
- G、CSL 的训练计划【BFS 贪心】(“新智认知”杯上海高校程序设计竞赛暨第十七届上海大学程序设计春季联赛)
题目传送门:https://ac.nowcoder.com/acm/contest/551/G 链接:https://ac.nowcoder.com/acm/contest/551/G来源:牛客网 题 ...
- F、CSL 的神奇序列 【规律】 (“新智认知”杯上海高校程序设计竞赛暨第十七届上海大学程序设计春季联赛)
题目传送门:https://ac.nowcoder.com/acm/contest/551/F 题目描述 CSL 有一个神奇的无穷实数序列,他的每一项满足如下关系: 对于任意的正整数 n ,有 n∑k ...
- E、CSL 的魔法 【模拟】 (“新智认知”杯上海高校程序设计竞赛暨第十七届上海大学程序设计春季联赛)
题目传送门:https://ac.nowcoder.com/acm/contest/551#question 题目描述 有两个长度为 n 的序列,a0,a1,…,an−1a0,a1,…,an−1和 b ...
随机推荐
- Solon rpc 之 SocketD 协议 - 消息订阅模式
Solon rpc 之 SocketD 协议系列 Solon rpc 之 SocketD 协议 - 概述 Solon rpc 之 SocketD 协议 - 消息上报模式 Solon rpc 之 Soc ...
- Windows下如何玩转火热的go-zero
作者:阿啄debugIT 前言 go-zero 是一个集成了各种工程实践的 web 和 rpc 框架.通过弹性设计保障了大并发服务端的稳定性,经受了充分的实战检验. go-zero 包含极简的 API ...
- 【SpringBoot1.x】RestfulCRUD
SpringBoot1.x RestfulCRUD 文章源码 添加资源 将所有的静态资源都添加到 src/main/resources/static 文件夹下,所有的模版资源都添加到 src/main ...
- 【C++】《C++ Primer 》第五章
第五章 语句 一.简单语句 表达式语句:一个表达式末尾加上分号,就变成了表达式语句. 空语句:只有一个单独的分号,记得注释说明提高代码可读性. 复合语句(块):用花括号 {}包裹起来的语句和声明的序列 ...
- 大数相加Java
题目 以字符串的形式读入两个数字,编写一个函数计算它们的和,以字符串形式返回. 分析 两个字符串,定义两个指针,分别从这两个字符串的结尾开始遍历,因为可能字符串1比字符串2长度要长,因此只要两者其中有 ...
- Thread线程源码解析,Java线程的状态,线程之间的通信
线程的基本概念 什么是线程 现代操作系统在运行一个程序的时候,会为其创建一个进程.例如,启动一个Java程序,操作系统就会创建一个Java进程.线代操作系统调度的最小单位是线程.也叫做轻量级进程.在一 ...
- Linux学习笔记 | docker基本命令
Docker的三大核心概念:镜像.容器.仓库 镜像:类似虚拟机的镜像.用俗话说就是安装文件. 容器:类似一个轻量级的沙箱,容器是从镜像创建应用运行实例,可以将其启动.开始.停止.删除.而这些容器都是相 ...
- Win 10 Docker安装和简单使用
Win 10 Docker安装和简单使用 1.环境准备 Docker for Windows需要运行在64位Windows 10 Pro专业版.企业版或教育版(1607年纪念更新,版本14393或更高 ...
- 详解MySQL执行事务的语法和流程
摘要:MySQL 提供了多种存储引擎来支持事务. MySQL 提供了多种存储引擎来支持事务.支持事务的存储引擎有 InnoDB 和 BDB,其中,InnoDB 存储引擎事务主要通过 UNDO 日志和 ...
- 【Android】报错 Please ensure Hyper-V is disabled in Windows Features, or refer to the Intel HAXM 的解决方案
参考文章 实测华为锐龙本(adm yes)安装Android avd虚拟机教程 环境 Android Studio 3.6; Windows 1909; AMD Ryzen 4800U with Ra ...