热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

CodeChef2014AprilChallenge-Chef的最终对决:数据结构与整体二分的应用

本题探讨了在大数据结构背景下,如何通过整体二分和CDQ分治等高级算法优化处理复杂的时间序列问题。题目设定包括节点数量、查询次数和权重限制,并详细分析了解决方案中的关键步骤。

问题描述

给定一棵树,包含n个节点(编号为1到n),每个节点有一个初始值wi (1 ≤ wi ≤ 10^9),以及q次操作。每次操作可能是更新某个节点的值或询问某个子树内非正数节点的数量。要求支持高效的数据结构来处理这些操作。

具体参数范围:
n, q, V ≤ 100,000
wi ≤ 10^9

解决方案

本题的核心难点在于处理带有下取整运算的时间相关修改。这类问题通常需要考虑不同时间点的影响累积方式,而不是简单地将所有变化叠加在一起。

我们观察到,一次更新操作的影响范围有限,仅限于距离不超过log(n)的节点。基于此特性,我们可以设计一个复杂度为O(q log n log² V)的初步算法:

  • 对于子树内的节点,根据BFS序维护受影响区间的减法操作。
  • 对于被修改节点的祖先节点,同样按照其对应深度进行相应调整,注意去除重复影响。

为了进一步优化,我们引入了一种更高效的策略:首先不直接处理子树,而是每次只修改当前节点及其祖先节点。通过记录tag[i,j]表示节点i对其第j级子孙的影响,可以将每次修改的复杂度降低至O(log²)。

针对查询子树内非正数节点的问题,可以采用整体二分或CDQ分治的方法。具体来说,我们将所有操作按时间分治,在每个分治区间[l,r]中,标记出哪些节点在此期间变为非正数。通过递归处理左右两个子区间,确保每个节点最多只会被检查O(log n)次。

此外,为了避免频繁插入和撤销操作带来的额外开销,我们使用持久化tag数组存储每次改变的时间戳。这样不仅减少了不必要的计算量,还将总的时间复杂度降至O(Q log² n)。

代码实现

#include 
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fod(i,a,b) for(int i=a;i>=b;--i)
#define N 100005
#define LL long long
using namespace std;

int fs[N], nt[2*N], dt[2*N], pr[N], n, m, w[N], dfw[N], sz[N], dfn[N], ans[N], m1, ask[N][3], f[N], dep[N];
LL sm[N];
//tree_array
int c[N];

int lowbit(int k) {
return k & -k;
}

int get(int k) {
int s = 0;
while (k) s += c[k], k -= lowbit(k);
return s;
}

void put(int k) {
while (k <= n) c[k]++, k += lowbit(k);
}

void link(int x, int y) {
nt[++m1] = fs[x];
dt[fs[x] = m1] = y;
}

void dfs(int k, int fa) {
f[k] = fa;
dfw[dfn[k] = ++dfn[0]] = k;
dep[k] = dep[fa] + 1;
sz[k] = 1;
for (int i = fs[k]; i; i = nt[i]) {
int p = dt[i];
if (p != fa) dfs(p, k), sz[k] += sz[p];
}
}

struct node {
LL v, t;
};

vector tag[N][32];
int le[N][32], now[N][32], d[N], u1[N], u2[N], ts[N];

void ins(int k, int s, int ti) {
if (!s || !k) return;
int v = s;
for (int c = 0; v; c++) {
int vl = (f[k]) ? v - (v >> 2) : v;
if (le[k][c] == 0) tag[k][c].push_back((node){vl, ti});
else tag[k][c].push_back((node){vl + tag[k][c][le[k][c] - 1].v, ti});
le[k][c]++;
v >>= 1;
}
ins(f[k], s >> 1, ti);
}

LL query(int k, int ti) {
LL s = 0;
for (int p = 0; p <= 31 && k; k = f[k], p++) {
while (now[k][p] while (now[k][p] > 0 && tag[k][p][now[k][p]].t > ti) now[k][p]--;
if (now[k][p] }
return s;
}

void doit(int l, int r, int x, int y) {
if (x > y) return;
if (l == r) {
fo(i, x, y) ts[d[i]] = l;
return;
}
int mid = (l + r) >> 1;
u1[0] = u2[0] = 0;
fo(i, x, y) {
if (pr[d[i]] <= query(d[i], mid)) u1[++u1[0]] = d[i];
else u2[++u2[0]] = d[i];
}
fo(j, 1, u1[0]) d[x + j - 1] = u1[j];
fo(j, 1, u2[0]) d[x + u1[0] + j - 1] = u2[j];
int md = x + u1[0] - 1;
doit(l, mid, x, md);
doit(mid + 1, r, md + 1, y);
}

bool cmp(int x, int y) {
return ts[x] }

int main() {
cin >> n;
fo(i, 1, n) scanf("%d", &pr[i]);
fo(i, 1, n - 1) {
int x, y;
scanf("%d%d", &x, &y);
link(x, y), link(y, x);
}
dfs(1, 0);
int q;
cin >> q;
fo(i, 1, q) {
scanf("%d%d", &ask[i][0], &ask[i][1]);
if (ask[i][0] == 1) {
scanf("%d", &ask[i][2]);
ins(ask[i][1], ask[i][2], i);
}
}
fo(i, 1, n) d[i] = i;
doit(1, q + 1, 1, n);
sort(d + 1, d + n + 1, cmp);
for (int i = 1, j = 1; i <= q; i++) {
while (j <= n && ts[d[j]] <= i) put(dfn[d[j]]), j++;
if (ask[i][0] == 2) printf("%d\n", get(dfn[ask[i][1]] + sz[ask[i][1]] - 1) - get(dfn[ask[i][1]] - 1));
}
}

推荐阅读
  • 2018-2019学年第六周《Java数据结构与算法》学习总结
    本文总结了2018-2019学年第六周在《Java数据结构与算法》课程中的学习内容,重点介绍了非线性数据结构——树的相关知识及其应用。 ... [详细]
  • 由二叉树到贪心算法
    二叉树很重要树是数据结构中的重中之重,尤其以各类二叉树为学习的难点。单就面试而言,在 ... [详细]
  • 主调|大侠_重温C++ ... [详细]
  • 本题来自WC2014,题目编号为BZOJ3435、洛谷P3920和UOJ55。该问题描述了一棵不断生长的带权树及其节点上小精灵之间的友谊关系,要求实时计算每次新增节点后树上所有可能的朋友对数。 ... [详细]
  • 深入解析Java虚拟机(JVM)架构与原理
    本文旨在为读者提供对Java虚拟机(JVM)的全面理解,涵盖其主要组成部分、工作原理及其在不同平台上的实现。通过详细探讨JVM的结构和内部机制,帮助开发者更好地掌握Java编程的核心技术。 ... [详细]
  • 在高并发需求的C++项目中,我们最初选择了JsonCpp进行JSON解析和序列化。然而,在处理大数据量时,JsonCpp频繁抛出异常,尤其是在多线程环境下问题更为突出。通过分析发现,旧版本的JsonCpp存在多线程安全性和性能瓶颈。经过评估,我们最终选择了RapidJSON作为替代方案,并实现了显著的性能提升。 ... [详细]
  • 本文介绍了如何在 C# 和 XNA 框架中实现一个自定义的 3x3 矩阵类(MMatrix33),旨在深入理解矩阵运算及其应用场景。该类参考了 AS3 Starling 和其他相关资源,以确保算法的准确性和高效性。 ... [详细]
  • 版本控制工具——Git常用操作(下)
    本文由云+社区发表作者:工程师小熊摘要:上一集我们一起入门学习了git的基本概念和git常用的操作,包括提交和同步代码、使用分支、出现代码冲突的解决办法、紧急保存现场和恢复 ... [详细]
  • 深入解析ESFramework中的AgileTcp组件
    本文详细介绍了ESFramework框架中AgileTcp组件的设计与实现。AgileTcp是ESFramework提供的ITcp接口的高效实现,旨在优化TCP通信的性能和结构清晰度。 ... [详细]
  • 在编译BSP包过程中,遇到了一个与 'gets' 函数相关的编译错误。该问题通常发生在较新的编译环境中,由于 'gets' 函数已被弃用并视为安全漏洞。本文将详细介绍如何通过修改源代码和配置文件来解决这一问题。 ... [详细]
  • 本题要求在一组数中反复取出两个数相加,并将结果放回数组中,最终求出最小的总加法代价。这是一个经典的哈夫曼编码问题,利用贪心算法可以有效地解决。 ... [详细]
  • 本文深入探讨了MySQL中常见的面试问题,包括事务隔离级别、存储引擎选择、索引结构及优化等关键知识点。通过详细解析,帮助读者在面对BAT等大厂面试时更加从容。 ... [详细]
  • 本文旨在探讨如何利用决策树算法实现对男女性别的分类。通过引入信息熵和信息增益的概念,结合具体的数据集,详细介绍了决策树的构建过程,并展示了其在实际应用中的效果。 ... [详细]
  • 采用IKE方式建立IPsec安全隧道
    一、【组网和实验环境】按如上的接口ip先作配置,再作ipsec的相关配置,配置文本见文章最后本文实验采用的交换机是H3C模拟器,下载地址如 ... [详细]
  • 目录一、salt-job管理#job存放数据目录#缓存时间设置#Others二、returns模块配置job数据入库#配置returns返回值信息#mysql安全设置#创建模块相关 ... [详细]
author-avatar
许雅惠嘉文意芝
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有