当前位置: 首页 > news >正文

【题解】洛谷 P11673 [USACO25JAN] Median Heap G [树形 dp]

P11673 [USACO25JAN] Median Heap G - 洛谷 (luogu.com.cn)

读完题,发现交换不需要代价,但改变需要,交换还是强制的。

我们定义 med(a,b,c) 为 a,b,c 的中位数,定义如下函数:

p_m(x)=\left\{\begin{matrix} 0\ (x < m)\\ 1\ (x=m)\\ 2\ (x>m) \end{matrix}\right.

发现:med(p_m(a),p_m(b),p_m(c))=p_m(med(a,b,c))

也就是说,我们不必在意每个节点权值之间的大小关系,而只用关注节点权值和 m 的关系。

考虑构造树形 dp,f[x][0 / 1 / 2] 分别代表节点 x 小于 / 等于 / 大于 m 的代价。

转移时,枚举 x 与它的左右孩子的 0 / 1 / 2 状态。

假设枚举 x 的旧状态为 k,x 的新状态就是三个状态的中位数(因为交换是强制的)。

代价为 x 变成 k 的代价 + 左右孩子枚举的状态代价。

这样时间复杂度为 O(3^3*log\ n*Q),悬。

考虑先提前给询问数组按 m 从小到大排序,最后按顺序遍历。

定义一个指针,每次只更新小于等于 m 的节点。

时间复杂度 O(3^3*log\ n*log\ Q)

但这样还不够,只有一个指针时,如果当前 m 大于 上一个 m。

那等于上一个 m 的节点应该改变,但单指针只会继续往后增加。

考虑使用双指针,一个处理小于 m,一个处理大于 m,能完全覆盖到。

代码:

#include<bits/stdc++.h>
using namespace std;#define lp (p << 1)
#define rp ((p << 1) | 1)typedef long long LL;
const int N = 2e5 + 10;
const LL inf = 1e18;LL a[N], c[N];
int n;struct node {LL a; int id;
} p[N];struct qus {LL m; int id;
} q[N];bool cmpa(node na, node nb) {return na.a < nb.a;
}bool cmpb(qus qa, qus qb) {return qa.m < qb.m;
}LL f[N][3], ans[N];int get_med(int i, int j, int k) {return i + j + k - min({i, j, k}) - max({i, j, k});
}void update(int p, LL m) {f[p][0] = f[p][1] = f[p][2] = inf;int w[3];if (a[p] < m) {w[0] = 0;w[1] = w[2] = c[p];}if (a[p] == m) {w[1] = 0;w[0] = w[2] = c[p];}if (a[p] > m) {w[2] = 0;w[0] = w[1] = c[p];}if (rp > n) {f[p][0] = w[0];f[p][1] = w[1];f[p][2] = w[2];return ;}for (int i = 0; i <= 2; i ++) {for (int j = 0; j <= 2; j ++) {for (int k = 0; k <= 2; k ++) {int mid = get_med(i, j, k);f[p][mid] = min(f[p][mid], f[lp][i] + f[rp][j] + w[k]);}}}
}void pushup(int p, int m) {while (p) {update(p, m);p >>= 1;}
}int main () {ios::sync_with_stdio(false);cin.tie(0);cin >> n;for(int i = 1; i <= n; i ++) {cin >> a[i] >> c[i];p[i] = {a[i], i};}sort(p + 1, p + n + 1, cmpa);int Q; cin >> Q;for (int i = 1; i <= Q; i ++) {cin >> q[i].m;q[i].id = i;}sort(q + 1, q + Q + 1, cmpb);for (int i = 1; i <= n; i ++) {for (int j = 0; j <= 2; j ++) {f[i][j] = inf;}}for (int i = n; i >= 1; i --) {update(i, 0);}int la = 1, lb = 1;for (int i = 1; i <= Q; i ++) {while (la <= n && p[la].a < q[i].m) {pushup(p[la].id, q[i].m);la ++;}while (lb <= n && p[lb].a <= q[i].m) {pushup(p[lb].id, q[i].m);lb ++;}ans[q[i].id] = f[1][1];}for (int i = 1; i <= Q; i ++) {cout << ans[i] << "\n";}
} 

http://www.dtcms.com/a/503400.html

相关文章:

  • 气球游戏(DP,分治)
  • MySQL同步连接池与TrinityCore的对比学习(六)
  • UserWarning: No file found at “C:\Faces\image_0032.jpg“AssertionError
  • 网站生成器下载wordpress 添加微博关注
  • 【个人成长笔记】Qt Creator快捷键终极指南:从入门到精通
  • 【开题答辩过程】以《校园可共享物品租赁系统的设计与实现》为例,不会开题答辩的可以进来看看
  • 北京高端网站定制公司猎头公司工作怎么样
  • StarRocks-基本介绍(一)基本概念、特点、适用场景
  • Java零基础入门:从封装到构造方法 --- OOP(上)
  • JAVA算法练习题day43
  • 如何学习Lodash源码?
  • 建个自己的网站难吗宁波 seo整体优化
  • uni-app详解
  • AI学习:SPIN -win-安装SPIN-工具过程 SPIN win 电脑安装=accoda 环境-第五篇:代码修复]
  • 【Linux】Linux:sudo 白名单配置与 GCC/G++ 编译器使用指南
  • PyTorch 张量初始化方法详解
  • 计算机理论学习Day16
  • 动物摄影网站佛山网站制作维护
  • springboot整合redis-RedisTemplate单机模式
  • 【Redisson】分布式锁原理和使用姿势
  • linux学习笔记(43)网络编程——HTTPS (补充)
  • HTTP Client/Server 理论
  • 怎么申请域名建立网站宁波网站建设开发
  • C++:内存管理 |内存分布|回顾|new/delete底层|实现原理|拓展|定位new|池化技术|总结区别对比
  • 上街网站建设做语文高考题网站
  • 前端基础二、CSS(一)、CSS基础知识
  • 【MySQL】第三章 运算符
  • 智能机器人梯控系统(含二维码/刷卡/人脸识别)安装布线指南,结合工程规范与安全要点进行结构化优化,内容清晰、可操作性强
  • 突破 @Valid 局限!Spring Boot 编程式验证深度解析与复杂场景实战
  • 盐城市规划建设局网站做北美市场用哪个网站