P7394 「TOCO Round 1」History

news/2024/10/10 9:42:00

操作树加二分,目前题解区没有这种做法。

发现操作一可逆,可以用操作树,操作三解决。

操作一单点修改没什么好说的。

接下来看操作二。令 \(fa_{x,k}\)\(x\)\(k\) 级祖先。

发现对于每个询问中,如果 \(y\) 为奇数那么答案为 \(0\)。如果 \(y\) 为偶数,那么答案就是 \(fa_{x,y/2}\)\(y/2\) 级儿子的开灯的个数减 \(fa_{x,y/2-1}\)\(y/2-1\) 级儿子的开灯的个数。

具体实现方法就是先对这棵树跑出每个点的 bfs 序和 dfs 序,记树的第 \(i\) 层最大的 bfs 序为 \(lst_i\)。所有深度为 \(d\) 的点的 bfs 序都在 \([lst_{d-1}+1,lst_d]\),在这个区间二分。

举个例子:

现在的询问 \(x=5,y=4\),那么 \(fa_{x,y/2}=2\),二分时如果二分出的点在以 \(fa_{x,y/2}\) 为根的子树内,视想要哪边的端点移动二分区间。如果不在这棵子树内,则与 \(fa_{x,y/2}\) 的 dfs 序比较。如果小,二分区间右移;如果大,二分区间左移。例如,目前二分到了 \(11\) 号节点,它的 dfs 序小于 \(2\) 的 dfs 序,那么二分区间右移。

最终答案为红色区间中的开灯个数减蓝色中的开灯个数。

用支持单点修改,区间求和的数据结构(例如树状数组)维护下就好了。

复杂度 \(O(n\log n)\)

#include <bits/stdc++.h>using namespace std;int read() {int s = 0, w = 1;char c = getchar();while (!isdigit(c)) {if (c == '-')w = -w;c = getchar();}while (isdigit(c)) {s = s * 10 + c - 48;c = getchar();}return s * w;
}
void pr(int x) {if (x < 0)putchar('-'), x = -x;if (x > 9)pr(x / 10);putchar(x % 10 + 48);
}
#define end_ putchar('\n')
#define spc_ putchar(' ')const int maxN = 1e5 + 7;int n, m;vector<int> E[maxN];int bfn[maxN], dfn[maxN], tot;
int dep[maxN], siz[maxN], lst[maxN], rk[maxN];int fa[25][maxN];void dfs(int x, int f) {dep[x] = dep[f] + 1;siz[x] = 1;dfn[x] = ++tot;fa[0][x] = f;for (int t = 1; t <= 20; t++)fa[t][x] = fa[t - 1][fa[t - 1][x]];for (int to : E[x])if (to != f) {dfs(to, x);siz[x] += siz[to];}
}
void bfs() {tot = 0;queue<int> Q;Q.push(1);while (!Q.empty()) {int f = Q.front();Q.pop();bfn[f] = ++tot;rk[tot] = f;for (int to : E[f])if (dep[to] > dep[f])Q.push(to);}
}int find(int x, int k) {for (int i = 0; k; i++, k >>= 1)if (k & 1)x = fa[i][x];return x;
}int cnt;
struct node {int to, x, y, id;node(int a, int b) {to = a, x = b;y = id = -1;}node(int a, int b, int c, int d) {to = a, x = b, y = c, id = d;}
};
vector<node> mo[maxN];int qcnt;
struct ques {int x, y, id;
};
vector<ques> q[maxN];
int ans[maxN];int v[maxN];
int t[maxN];
void add(int x, int v) {for (; x <= n; x += x & -x)t[x] += v;
}
int ask(int x) {int res = 0;for (; x > 0; x -= x & -x)res += t[x];return res;
}int solve(int x, int y) {if (y == 0)return v[x];if (y & 1)return 0;y >>= 1;int f = find(x, y);if (!f)return 0;auto erfen = [x](bool ty, int f) {int L = lst[dep[x] - 1] + 1, R = lst[dep[x]];int ans = -1;while (L <= R) {int mid = (L + R) >> 1;int p = rk[mid];if (dfn[f] <= dfn[p] && dfn[p] <= dfn[f] + siz[f] - 1) {ans = p;if (ty)R = mid - 1;elseL = mid + 1;}else if (dfn[p] < dfn[f])L = mid + 1;elseR = mid - 1;}return ans;};int l = erfen(true, f), r = erfen(false, f);int res = ask(bfn[r]) - ask(bfn[l] - 1);f = find(x, y - 1);l = erfen(true, f), r = erfen(false, f);int tmp = ask(bfn[r]) - ask(bfn[l] - 1);return res - tmp;
}void calc(int x) {for (auto i : mo[x]) {if (i.x != -1 && i.id == -1) {if (v[i.x])v[i.x] = 0, add(bfn[i.x], -1);elsev[i.x] = 1, add(bfn[i.x], 1);}if (i.id != -1)ans[i.id] = solve(i.x, i.y);calc(i.to);if (i.x != -1 && i.id == -1) {if (v[i.x])v[i.x] = 0, add(bfn[i.x], -1);elsev[i.x] = 1, add(bfn[i.x], 1);}}
}int main() {n = read();for (int i = 1; i < n; i++) {int u = read(), v = read();E[u].push_back(v);E[v].push_back(u);}dfs(1, 0);bfs();for (int i = 1; i <= n; i++)lst[dep[i]] = max(lst[dep[i]], bfn[i]);memset(ans, 255, sizeof(ans));m = read();for (int i = 1; i <= m; i++) {int op = read();if (op == 1) {int x = read();mo[cnt].emplace_back(cnt + 1, x);++cnt;}if (op == 2) {int x = read(), y = read();mo[cnt].emplace_back(cnt + 1, x, y, i);++cnt;}if (op == 3) {int x = read();mo[x].emplace_back(cnt + 1, -1);++cnt;}}calc(0);for (int i = 1; i <= m; i++)if (ans[i] != -1)pr(ans[i]), end_;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/69685.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

php网站忘记后台密码忘记怎么办

如果你忘记了PHP网站后台的登录密码,可以通过以下几种方法来尝试恢复或重置密码:检查邮箱:如果在创建账户时设置了找回密码的功能,并且绑定了邮箱,可以先检查注册时使用的邮箱是否有找回密码的邮件。数据库直接修改:通过phpMyAdmin或其他数据库管理工具登录到MySQL数据库…

公司网站新闻图片修改方式

要修改公司网站上的新闻图片,通常可以按照以下步骤操作:备份原图:在进行任何修改之前,确保先备份原始图片文件,以防修改后不满意或出现其他问题。选择工具:根据需要修改的内容选择合适的图像编辑工具。常见的工具有Photoshop、GIMP(免费开源软件)或者在线编辑器如Canva…

网站提示数据库连接错误

当遇到网站提示数据库连接错误时,可以按照以下步骤进行排查和解决:检查数据库服务器状态:确认数据库服务是否正常运行。 使用命令行工具或管理界面尝试连接数据库。检查配置信息:核对应用中的数据库连接配置(如用户名、密码、主机地址、端口号)是否正确。 确保配置文件没…

宝塔面板忘记管理员用户名密码简单有效解决方法

宝塔面板是一款流行的服务器管理工具,如果忘记了管理员的用户名或密码,可以通过以下步骤来尝试恢复:登录宝塔官网获取帮助访问宝塔官网或者官方论坛,查找相关问题的解决方案。通过命令行重置密码使用SSH工具连接到服务器。 输入以下命令重置密码:bashpt-login按照提示操作…

网站修改后台登录密码

要修改网站后台的登录密码,通常可以通过以下几个步骤来实现:登录后台: 使用当前的用户名和密码登录到网站的管理后台。 进入用户设置: 在后台管理界面找到用户设置或个人信息设置的相关选项。 密码修改页面: 在用户设置中找到修改密码的选项或链接。 填写新密码: 按照提示输入…

河道水位自动监测预警系统

河道水位自动监测预警系统基于AI视频智能水尺读数技术,河道水位自动监测预警系统通过在河道周边布设监控摄像头,实时监测水位的变化。河道水位自动监测预警系统利用人工智能视觉分析技术,进行水位趋势分析和预测。一旦水位超过预设阈值,河道水位自动监测预警系统将自动发出…

帝国cms网站安装时找不到“增加信息”的地方怎么办?

安装时找不到“增加信息”的地方原因:未增加栏目。 解决:先增加栏目,然后再增加信息。扫码添加技术【解决问题】专注中小企业网站建设、网站安全12年。熟悉各种CMS,精通PHP+MYSQL、HTML5、CSS3、Javascript等。承接:企业仿站、网站修改、网站改版、BUG修复、问题处理、二次…

CSP 集训(9.23-9.26)

更新了 CSP-3 网络流那道题解法 updated on 9.26用来整理模拟赛等9.23 csp-3【noip23 ZR二十连测 DAY10】 保龄. A.奇观 狗市题目描述。不是这题意太大歧义了吧,我讨厌的第二种出题人——题意描述相当不清。CTH:13 座城市又不代表是 13 座不同的城市。直接看形式化题目的话(…