热门标签 | 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));
}
}

推荐阅读
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • 深入解析Android自定义View面试题
    本文探讨了Android Launcher开发中自定义View的重要性,并通过一道经典的面试题,帮助开发者更好地理解自定义View的实现细节。文章不仅涵盖了基础知识,还提供了实际操作建议。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • Explore how Matterverse is redefining the metaverse experience, creating immersive and meaningful virtual environments that foster genuine connections and economic opportunities. ... [详细]
  • 本文介绍了Java并发库中的阻塞队列(BlockingQueue)及其典型应用场景。通过具体实例,展示了如何利用LinkedBlockingQueue实现线程间高效、安全的数据传递,并结合线程池和原子类优化性能。 ... [详细]
  • 本文详细探讨了KMP算法中next数组的构建及其应用,重点分析了未改良和改良后的next数组在字符串匹配中的作用。通过具体实例和代码实现,帮助读者更好地理解KMP算法的核心原理。 ... [详细]
  • Explore a common issue encountered when implementing an OAuth 1.0a API, specifically the inability to encode null objects and how to resolve it. ... [详细]
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • 本文详细介绍了Akka中的BackoffSupervisor机制,探讨其在处理持久化失败和Actor重启时的应用。通过具体示例,展示了如何配置和使用BackoffSupervisor以实现更细粒度的异常处理。 ... [详细]
  • Android 渐变圆环加载控件实现
    本文介绍了如何在 Android 中创建一个自定义的渐变圆环加载控件,该控件已在多个知名应用中使用。我们将详细探讨其工作原理和实现方法。 ... [详细]
  • 在金融和会计领域,准确无误地填写票据和结算凭证至关重要。这些文件不仅是支付结算和现金收付的重要依据,还直接关系到交易的安全性和准确性。本文介绍了一种使用C语言实现小写金额转换为大写金额的方法,确保数据的标准化和规范化。 ... [详细]
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • 本文探讨了如何在给定整数N的情况下,找到两个不同的整数a和b,使得它们的和最大,并且满足特定的数学条件。 ... [详细]
  • 本文介绍了如何通过 Maven 依赖引入 SQLiteJDBC 和 HikariCP 包,从而在 Java 应用中高效地连接和操作 SQLite 数据库。文章提供了详细的代码示例,并解释了每个步骤的实现细节。 ... [详细]
  • 本文介绍如何使用阿里云的fastjson库解析包含时间戳、IP地址和参数等信息的JSON格式文本,并进行数据处理和保存。 ... [详细]
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社区 版权所有