首页 > 其他分享 >P7710 [Ynoi2077] stdmxeypz 题解

P7710 [Ynoi2077] stdmxeypz 题解

时间:2023-10-08 21:33:32浏览次数:41  
标签:stdmxeypz ch 题解 复杂度 deep P7710 dfn sqrt 单次

P7710 [Ynoi2077] stdmxeypz 题解

我的第一道 Ynoi 题,体验感不高,调了大半天,最后发现有个地方 \(B_1\) 写成 \(B_2\) 了。

分析

树上问题,明显是要转到树下的,所以 DFS 序是一定要求的。

有关树上距离,所以 \(deep\) 数组也是一定要求的。

所以我们现在把问题转化成了:

给你三个序列 \(dfn, deep, val\),支持两个操作:

  1. 对于所有的 \(dfn_i \in [l, r]\) 且 \(deep_i \bmod x = y\),令 \(val_i\) 加上 \(z\);

  2. 求 \(val_i\) 的值。

有取模,应该不难想到根号分治。或者如果你做了 P5309 [Ynoi2011] 初始化,也能一眼看出来是根号分治,那个题就是这个题的序列版。

题解

先声明几个东西:

  • 算复杂度时认为 \(n, m\) 同阶。

  • \(dfn_i\) 表示 \(i\) 的 DFS 序;

  • \(deep_i\) 表示 \(dfn = i\) 的点的深度;

  • \(val_i\) 表示 \(dfn = i\) 的点的权值;

  • \(l_i\) 表示以 \(i\) 为根的子树里最小的 \(dfn\),其实就是它自身的 \(dfn\);

  • \(r_i\) 表示以 \(i\) 为根的子树里最大的 \(dfn\),其实就是 \(l_i + size_i - 1\);

  • \(y\) 与给出的 \(y\) 不同。当给出操作一时,因为我们要找一些 \(i\) 使 \((deep_i - deep_{dfn_v}) \bmod x = y\),所以我们设 \(y = (deep_{dfn_v} + y) \bmod x\)。

既然是根号分治,我们得想分治什么。这个题比较明显了,既然是对 \(x\) 取模,那肯定分治 \(x\)。

所以设一个阈值 \(B_1\),将第一种操作再分成两类,\(x\) 小于等于 \(B_1\) 的分为一类,大于 \(B_1\) 的分为一类。

我们考虑怎么处理这两类操作。

先考虑小于 \(B_1\) 的,感觉这一部分比较好想。

考虑一下我们需要枚举什么、有什么限制:

  • 我们需要从 \(l\) 到 \(r\) 枚举一个 \(i\);

  • 当 \(deep_i \bmod x = y\) 时,使 \(val_i\) 加上 \(z\)。

所以我们可以设一个 \(f_{i, j, k}\) 表示 \(dfn = i\) 的点的深度 \(\bmod j = k\) 时需要让它的权值加上多少。

这样单次修改是 \(O(n)\) 的,单次查询是 \(O(1)\) 的,且空间复杂度为 \(O(n^2)\),一共要修改 \(m\) 次,查询 \(m \sqrt n\) 次,明显不行。

所以序列分块一下,\(f_{i, j, k}\) 表示 \(dfn\) 在第 \(i\) 个块内且深度 \(\bmod x = y\) 的点的权值需要加多少。单次修改 \(O(\sqrt n)\),单次查询 \(O(\sqrt n)\),空间复杂度 \(O(n \sqrt n)\),调调块长能过。

然后再来考虑大于 \(B_2\) 的操作。

我们先把每一个点看做二维的,坐标为 \((deep_{dfn_i}, dfn_i)\)。

因为模数大于阈值,所以考虑直接暴跳,最多暴跳 \(\displaystyle \frac{n}{B_1}\) 次。跳到每一个 \(deep\),直接暴力修改这一深度下 \(dfn\) 在 \([l, r]\) 区间内的点。

这样单次修改是 \(O(n)\) 的,单次查询是 \(O(1)\) 的,且空间复杂度为 \(O(n^2)\),一共要修改 \(m \sqrt n\) 次,查询 \(m\) 次,明显不行。

所以考虑序列差分分块,数组 \(\sum_{k = 1}^j cha_{i, k}\) 表示深度为 \(i\) 且 \(dfn\) 在第 \(j\) 个块内的点,权值需要加上多少。单次修改 \(O(1)\),单次查询 \(O(\sqrt n)\),空间复杂度 \(O(n \sqrt n)\),调调块长能过。

阈值 \(B_1\) 设到 \(\sqrt n\) 左右,块长 \(B_2\) 设到 \(2000\) 左右(或者说你需要保证 \(O(\frac{n^2}{B_2})\) 的空间复杂度能过),并不觉得卡常。

代码

#include <bits/stdc++.h>
#define M 300005

using namespace std;

inline int read() {
    int x = 0, s = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9') {
        if(ch == '-')
            s = -s;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9') {
        x = (x << 3) + (x << 1) + ch - '0';
        ch = getchar();
    }
    return x * s;
}

void write(int x) {
    if(x < 0)  {
        x = ~(x - 1);
        putchar('-');
    }
    if(x > 9)
        write(x / 10);
    putchar(x % 10 + 48);
}

const int B1 = 500, B2 = 2000;
int n, q, tim, ld[M], rd[M], deep[M], maxdeep;
int to[M << 1], head[M], nex[M << 1], cnt;
int belong[M], cha[M][251], res[M + B2 + 1], f[B1][B1][B1];

inline void add_edge(int u, int v) {
    to[++ cnt] = v;
    nex[cnt] = head[u];
    head[u] = cnt;
}

void dfs(int u, int fu) {
    ld[u] = ++ tim;
    deep[ld[u]] = deep[ld[fu]] + 1;
    maxdeep = max(maxdeep, deep[ld[u]]);
    for(int i = head[u]; i; i = nex[i])
        if(to[i] != fu)
            dfs(to[i], u);
    rd[u] = tim;
}

signed main() {
    n = read();
    q = read();
    belong[1] = 1;
    for(int i = 2; i <= n; ++ i) {
        int u = read();
        add_edge(u, i);
        add_edge(i, u);
        belong[i] = (i - 1) / B2 + 1;
    }
    dfs(1, 0);
    for(int i = 1; i <= q; ++ i) {
        int opt = read(), v = read(), l = ld[v], r = rd[v];
        if(opt == 1) {
            int x = read(), y = read(), z = read();
            y = (deep[l] + y) % x;
            if(x <= B1) {
                if(belong[l] == belong[r]) {
                    for(int j = l; j <= r; ++ j)
                        if(deep[j] % x == y)
                            res[j] += z;
                }
                else {
                    for(int j = l; j <= belong[l] * B2; ++ j)
                        if(deep[j] % x == y)
                            res[j] += z;
                    for(int j = B2 * (belong[r] - 1) + 1; j <= r; ++ j)
                        if(deep[j] % x == y)
                            res[j] += z;
                    for(int j = belong[l] + 1; j < belong[r]; ++ j)
                        f[j][x][y] += z;
                }
            }
            else {
                if(belong[l] == belong[r]) {
                    for(int j = l; j <= r; ++ j)
                        if(deep[j] % x == y)
                            res[j] += z;
                }
                else {
                    for(int j = l; j <= belong[l] * B2; ++ j)
                        if(deep[j] % x == y)
                            res[j] += z;
                    for(int j = B2 * (belong[r] - 1) + 1; j <= r; ++ j)
                        if(deep[j] % x == y)
                            res[j] += z;
                    for(int j = y; j <= maxdeep; j += x)
                        cha[j][belong[l] + 1] += z, cha[j][belong[r]] -= z;
                }
            }
        }
        else {
            int ans = res[l];
            for(int j = 1; j <= belong[l]; ++ j)
                ans += cha[deep[l]][j];
            for(int j = 1; j <= B1; ++ j)
                ans += f[belong[l]][j][deep[l] % j];
            write(ans), putchar('\n');
        }
    }
}

标签:stdmxeypz,ch,题解,复杂度,deep,P7710,dfn,sqrt,单次
From: https://www.cnblogs.com/Meteor-streaking/p/17750208.html

相关文章

  • 「Round C10 B」间隔 题解
    简要题意本题有\(T\)组数据。给定一个由\(n\)个元素构成的正整数数列\(a_1,a_2,a_3...a_{n-1},a_n\)。问至少需要插入多少个整数才能使得\(a\)的各相邻元素之差相等(不能插入在头尾)。\(a\)数列保证是单调不减的。\(1\len\le10^6,0\lea_i\le10^6,1\leT\le1......
  • DBeaver [安装/问题解决]
     DBeaverMac版软件简介DBeaverMac版是一款专门为开发人员和数据库管理员设计的免费开源通用数据库工具。软件的易用性是它的宗旨,是经过精心设计和开发的数据库管理工具。免费、跨平台、基于开源框架和允许各种扩展写作(插件)。下载地址......
  • 【题解】CodeForces-1874/1875
    CodeForces-1875AJellyfishandUndertale一定是等待降到\(1\)或者能补满到\(a\)时才使用工具,依题意模拟即可。提交记录:Submission-CodeForcesCodeForces-1874AJellyfishandGame这种题目有点思路但是不是很会。赛时第一发写得根据奇偶性判断,\(k\)为偶数错了,然后感......
  • AtCoder Beginner Contest 323 (ABC 323) D、E、F 题解
    AtCoderBeginnerContest323(ABC323)D、E、F题解D题目大意给\(n\)种数\(s_i\),每一种数有\(c_i\)个,每次可以把两个相同的数合并为一个数,问最后会剩下多少数?分析对于每一个数\(s_i\),它最多被分解\(log_2c_i\)次,并且合并出来最大的数的大小小于\(s_i\timesc_i......
  • Hadoop问题解决(3)
    在启动hadoop过程中,出现如下错误:192.168.10.100:Invalidmaximumheapsize:-Xmx0m192.168.10.100:CouldnotcreatetheJavavirtualmachine.192.168.10.100:jobtracker已死,但pid文件仍存此时查看jobtracker的日志,1[root@ccloud100manager]#vim/var/log/hado......
  • hadoop问题解决(4)
    默认配置是将datanode,namenode,jobtracker,tasktracker,secondarynamenode的pid存放在/tmp目录下,随着linux的定期清理,这些pid就不见了,当然就无法停止了,怎么解决呢?在/tmp目录创建或者修改hadoop-hadoop用户名-datanode.pid 里面写入对应的pid, 可通过jps查看. namen......
  • 【UVA 12657】Boxes in a Line 题解(静态双向链表)
    您在编号为1的表格上有n个方框。n从左到右。您的任务是模拟4命令类型:•1XY:将框X向左移动到Y(如果X已经是Y的左侧,则忽略此项)•2XY:将框X向右移动到Y(如果X已经是Y的右侧,则忽略此项)•3XY:交换盒X和Y•4:反转整条线路。命令保证有效,即X不等于Y。例如,如果n=6,在执行114之后,该行......
  • 题解:洛谷P1119 灾后重建
    题解:洛谷P1119灾后重建题目传送门前言:没有掌握floyed求最短路的精髓是每次增加选一个中转点,导致写了2h才勉强卡过法1:最暴力的想法就是开个三维数组把前i个点的dis状态全部存下来,跑N次floyed,当然由于每次点数时递增的,所以实际复杂度远远小于O(N^4),算了下大概200个点跑了4e8多一......
  • 网络规划设计师真题解析--独立磁盘冗余阵列(二)(容量的计算)
    假如有3块容量是160G的硬盘做RAID5阵列,则这个RADI5的容量是(1);而如果有2块160G的盘和1块80G的盘,此时RAID5的容量是(2)。(1)A.320G    B.160G     C.80G     D.40G(2)A.40G     B.80G     C.160G    D.200G答案:(1)A (2)C解析:常见的RAID......
  • destoon : 后台无法登录问题解决
    经常有朋友在destoon搬家的时候,数据还原之后,会出现后台无法登录的情况.具体表现为后台帐号密码输入后点击确定,页面刷新.并没有跳转到相应后台页面.但是如果帐号密码输入错误,会提示密码错误的情况.这种情况多半是原系统设置中,设置了cookie作用域的问题,如......