[十二省联考2019]D2T2春节十二响
嘟嘟嘟
这题真没想到这么简单……
首先有60分大礼:\(O(n ^ 2logn)\)贪心。(我也不知道为啥就是对的)
然后又送15分链:维护两个堆,每次去堆顶的最大值。
这时候得到75分已经很开心了,但其实离AC也就差一点点。
链的做法已经给了我们提示:合并两个堆。其实这就相当于二叉树。那多叉树呢?就合并多个堆呗!从子树向上递归的时候不断将子树启发式合并,复杂度就保证了。
代码真的很短
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
#define enter puts("")
#define space putchar(' ')
#define Mem(a, x) memset(a, x, sizeof(a))
#define In inline
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-8;
const int maxn = 2e5 + 5;
inline ll read()
{
ll ans = 0;
char ch = getchar(), last = ' ';
while(!isdigit(ch)) last = ch, ch = getchar();
while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
if(last == '-') ans = -ans;
return ans;
}
inline void write(ll x)
{
if(x < 0) x = -x, putchar('-');
if(x >= 10) write(x / 10);
putchar(x % 10 + '0');
}
int n, a[maxn];
struct Edge
{
int nxt, to;
}e[maxn];
int head[maxn], ecnt = -1;
In void addEdge(int x, int y)
{
e[++ecnt] = (Edge){head[x], y};
head[x] = ecnt;
}
priority_queue<int> q[maxn];
int siz[maxn], tp[maxn];
In int dfs(int now)
{
int id1 = now;
for(int i = head[now], v; ~i; i = e[i].nxt)
{
v = e[i].to;
int id2 = dfs(v);
if(q[id1].size() < q[id2].size()) swap(id1, id2);
int Siz = q[id2].size();
for(int j = 1; j <= Siz; ++j) tp[j] = q[id1].top(), q[id1].pop();
for(int j = 1; j <= Siz; ++j)
{
q[id1].push(max(tp[j], q[id2].top()));
q[id2].pop();
}
}
q[id1].push(a[now]);
return id1;
}
int main()
{
Mem(head, -1);
n = read();
for(int i = 1; i <= n; ++i) a[i] = read();
for(int i = 2, x; i <= n; ++i) x = read(), addEdge(x, i);
int id = dfs(1);
ll ans = 0;
while(!q[id].empty()) ans += q[id].top(), q[id].pop();
write(ans), enter;
return 0;
}
这题我考场上写了75分,结果成绩一出只剩20分了,当时真的怀疑人生,因为我对自己的暴力有十足的信心。然后查代码的时候看到了触目惊心的一幕:
```
if(judge_line) {work1(); return 0;}
```
天知道我`judge_line()`后面的括号去哪了。
-Wall没给我报错,自己复查的时候也没发现,编译也能过,就这样白白没了55分。
考场代码全放上来吧
```c++
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define enter puts("")
#define space putchar(' ')
#define Mem(a, x) memset(a, x, sizeof(a))
#define In inline
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-8;
const int maxn = 2e5 + 5;
const int N = 18;
In ll read()
{
ll ans = 0;
char ch = getchar(), las = ' ';
while(!isdigit(ch)) las = ch, ch = getchar();
while(isdigit(ch)) ans = (ans = 10) write(x / 10);
putchar(x % 10 + '0');
}
In void MYFILE()
{
#ifndef mrclr
freopen("spring.in", "r", stdin);
freopen("spring.out", "w", stdout);
#endif
}
int n, a[maxn];
struct Edge
{
int nxt, to;
}e[maxn];
int head[maxn], ecnt = -1;
In void addEdge(int x, int y)
{
e[++ecnt] = (Edge){head[x], y};
head[x] = ecnt;
}
int fa[N + 2][maxn], dep[maxn], siz[maxn];
In void dfs(int now, int _f)
{
siz[now] = 1;
for(int i = 1; (1 << i) <= dep[now]; ++i)
fa[i][now] = fa[i - 1][fa[i - 1][now]];
for(int i = head[now], v; ~i; i = e[i].nxt)
{
if((v = e[i].to) == _f) continue;
dep[v] = dep[now] + 1, fa[0][v] = now;
dfs(v, now);
siz[now] += siz[v];
}
}
In int lca(int x, int y)
{
if(dep[x] < dep[y]) swap(x, y);
for(int i = N; i >= 0; --i)
if(dep[x] - (1 << i) >= dep[y]) x = fa[i][x];
if(x == y) return x;
for(int i = N; i >= 0; --i)
if(fa[i][x] ^ fa[i][y]) x = fa[i][x], y = fa[i][y];
return fa[0][x];
}
struct Node
{
int val, siz, id;
In bool operator < (const Node& oth)const
{
return val > oth.val || (val == oth.val && siz < oth.siz);
}
}t[maxn];
vector vec[maxn];
int cnt = 0;
ll ans = 0;
In void work0()
{
for(int i = 1; i <= n; ++i) t[i] = (Node){a[i], siz[i], i};
sort(t + 1, t + n + 1);
for(int i = 1; i <= n; ++i)
{
bool flg1 = 0;
for(int j = 1; j <= cnt && !flg1; ++j)
{
bool flg2 = 1;
for(int k = 0; k < (int)vec[j].size() && flg2; ++k)
{
int v = vec[j][k], z = lca(t[i].id, v);
if(z == v || z == t[i].id) flg2 = 0;
}
if(flg2) vec[j].push_back(t[i].id), flg1 = 1;
}
if(!flg1) vec[++cnt].push_back(t[i].id), ans += t[i].val;
}
write(ans), enter;
}
int du[maxn];
In bool judge_line()
{
for(int i = 1; i <= n; ++i) if(du[i] > 2) return 0;
return 1;
}
priority_queue q[3];
In void dfs1(int now, int _f, int pos)
{
q[pos].push(a[now]);
for(int i = head[now]; ~i; i = e[i].nxt)
dfs1(e[i].to, now, pos);
}
In void work1()
{
for(int i = head[1], j = 1; ~i; i = e[i].nxt, ++j)
dfs1(e[i].to, 1, j);
while(!q[1].empty() || !q[2].empty())
{
if(q[2].empty()) {ans += q[1].top(), q[1].pop(); continue;}
if(q[1].empty()) {ans += q[2].top(), q[2].pop(); continue;}
if(q[1].top() >= q[2].top()) ans += q[1].top();
else ans += q[2].top();
q[1].pop(), q[2].pop();
}
write(ans + a[1]), enter;
}
int main()
{
MYFILE();
Mem(head, -1);
n = read();
for(int i = 1; i <= n; ++i) a[i] = read();
for(int i = 2; i <= n; ++i)
{
int x = read();
addEdge(x, i);
++du[x], ++du[i];
}
if(judge_line) {work1(); return 0;}
dfs(1, 0);
if(n <= 2000) {work0(); return 0;}
work0();
return 0;
}
/*
8
1 5 2 3 4 1 4 2
1 2 1 3 4 5 7
*/
[十二省联考2019]D2T2春节十二响的更多相关文章
- 「洛谷5290」「LOJ3052」「十二省联考 2019」春节十二响【启发式合并】
题目链接 [洛谷传送门] [LOJ传送门] 题目大意 给定一棵树,每次选取树上的一个点集,要求点集中的每个点不能是另一个点的祖先,选出点集的代价为点集中权值最大点的权值,问将所有点都选一遍的最小代价为 ...
- LOJ#3052. 「十二省联考 2019」春节十二响(启发式合并)
题面 传送门 题解 先考虑一条链的情况,对于\(1\)号点来说,肯定是左子树中最大值和右子树中最大值一组,左子树中次大值和右子树中次大值一组--以此类推 那么如果不是一条链呢?我们把所有的链合并起来就 ...
- Solution -「十二省联考2019」春节十二响
题目 题意简述 link. 给一棵 \(n\) 个结点的有根树,点带权.把点分为若干组,并要求同组内不存在任何祖先-后代关系.最小化每组内的最大点权之和. 数据规模 \(n\le2\tim ...
- 「ZJOI2019」&「十二省联考 2019」题解索引
「ZJOI2019」&「十二省联考 2019」题解索引 「ZJOI2019」 「ZJOI2019」线段树 「ZJOI2019」Minimax 搜索 「十二省联考 2019」 「十二省联考 20 ...
- P5290 [十二省联考2019]春节十二响
题目地址:P5290 [十二省联考2019]春节十二响 骗分方法 如果你实在一点思路也没有,暴力都不会打,那么请考虑一下骗分. 方法一 输出所有 \(M\) 的和. 期望得分:0分. 实际还有5分 方 ...
- P5290 [十二省联考2019]春节十二响(堆+启发式合并)
P5290 [十二省联考2019]春节十二响 从特殊到一般 我们先看链的情况. 我们把点$1$左右的两条子链分别扔入堆里 每次取出两个堆的最大值,把答案累加上更大的那个(另一堆为空则直接加上去). 那 ...
- [十二省联考2019]字符串问题——后缀自动机+parent树优化建图+拓扑序DP+倍增
题目链接: [十二省联考2019]字符串问题 首先考虑最暴力的做法就是对于每个$B$串存一下它是哪些$A$串的前缀,然后按每组支配关系连边,做一遍拓扑序DP即可. 但即使忽略判断前缀的时间,光是连边的 ...
- [十二省联考2019]异或粽子——可持久化trie树+堆
题目链接: [十二省联考2019]异或粽子 求前$k$大异或区间,可以发现$k$比较小,我们考虑找出每个区间. 为了快速得到一个区间的异或和,将原序列做前缀异或和. 对于每个点作为右端点时,我们维护出 ...
- 【BZOJ5495】[十二省联考2019]异或粽子(主席树,贪心)
[BZOJ5495][十二省联考2019]异或粽子(主席树,贪心) 题面 BZOJ 洛谷 题解 这不是送分题吗... 转异或前缀和,构建可持久化\(Trie\). 然后拿一个堆维护每次的最大值,每次如 ...
随机推荐
- 3星|路江涌《共演战略画布》:PPT技巧级别的创新,缺实际分析案例
作者用自己的思路综合现有各种战略思想,给出企业各阶段各要素的战略分析工具.主要是2*2矩阵和双S曲线两种工具. 从书中的插图来看,这些工具在PPT演示中效果应该会不错. 作者在书中用这些工具做的分析不 ...
- 使用正则替换script及其内容
因做微信公众号文章保存,发现他的js大多数也用不着,所以就想着用正则替换掉源代码中的js片段 正则代码: <script(?:[^<]++|<(?!/script>))*+&l ...
- 使用whistle模拟cgi接口异常:错误码、502、慢网速、超时
绝大多数程序只考虑了接口正常工作的场景,而用户在使用我们的产品时遇到的各类异常,全都丢在看似 ok 的 try catch 中.如果没有做好异常的兼容和兜底处理,会极大的影响用户体验,严重的还会带来安 ...
- java.lang.ClassNotFoundException: org.I0Itec.zkclient.IZkStateListener异常解决
在启动Dubbo项目时,出现该异常 java.lang.ClassNotFoundException: org.I0Itec.zkclient.IZkStateListener 解决,引入 <d ...
- webpack学习笔记一:安装webpack、webpack-dev-server、内存加载js和html文件、loader处理非js文件
一 .webpack学习环境准备: 1:window系统 2:安装node.js 官方网址 下载好后下一步下一步安装即可 安装步骤略过....... 3:nrm的安装 打开cmd命令控制台 输入:n ...
- Oracle和Mysql获取uuid的方法对比
场景:orm框架用mybatis,需要往数据库新增一条数据,用Oracle和mysql数据库分别需要怎么实现? mysql方法,用mysql提供的uuid函数 <insert id=" ...
- [Abp 源码分析]零、文章目录
0.系列文章目录 一.Abp 框架启动流程分析 二.模块系统 三.依赖注入 四.模块配置 五.系统设置 六.工作单元的实现 七.仓储与 Entity Framework Core 八.缓存管理 九.事 ...
- Android状态栏着色
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 状态栏着色,也就是我们经常听到的沉浸式状态栏,关于沉浸式的称呼网上也有很多吐槽的,这里就不做过多讨论了,以下我们统称状态栏着色,这样 ...
- 时序数据库连载系列:指标届的独角兽Prometheus
简介 Prometheus是SoundCloud公司开发的一站式监控告警平台,依赖少,功能齐全.于2016年加入CNCF,广泛用于 Kubernetes集群的监控系统中,2018.8月成为继K8S之后 ...
- rabbitmq高级消息队列
rabbitmq使用 什么是消息队列 消息(Message)是指在应用间传送的数据.消息可以非常简单,比如只包含文本字符串,也可以很复杂,可以包含嵌入对象. 消息队列是一种应用间的通信方式,消息发送后 ...