博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj 1095 [ZJOI2007]Hide 捉迷藏 动态点分治+堆
阅读量:4551 次
发布时间:2019-06-08

本文共 4315 字,大约阅读时间需要 14 分钟。

题面

解法

挺恶心的题

考虑动态点分治,先建出点分树

然后每一个点开两个堆,分别为\(a,b\)

\(a_i\)表示点分树上\(i\)子树中所有节点在原树上和点分树中\(i\)父亲的距离,\(b_i\)表示点分树中\(i\)所有儿子的堆顶

再开一个堆\(ans\),存每一个\(b_i\)最大和次大值的和

在修改的时候,分两种情况考虑

但是本质都是一样的,就是在点分树上不断爬,爬到根为止,然后对当前点和父亲的\(a,b\)进行删除和加入

细节比较多,需要注意

重点:传入一个结构体参数的时候一定要加&,否则会T成皮皮

时间复杂度:\(O(q\ log^2\ n)\)

代码

#include 
#define inf 1 << 30#define N 100010using namespace std;template
void chkmax(node &x, node y) {x = max(x, y);}template
void chkmin(node &x, node y) {x = min(x, y);}template
void read(node &x) { x = 0; int f = 1; char c = getchar(); while (!isdigit(c)) {if (c == '-') f = -1; c = getchar();} while (isdigit(c)) x = x * 10 + c - '0', c = getchar(); x *= f;}struct Heap { priority_queue
ret, del; void push(int x) {ret.push(x);} void erase(int x) {del.push(x);} int siz() {return ret.size() - del.size();} void Pop() { while (!ret.empty() && !del.empty() && ret.top() == del.top()) ret.pop(), del.pop(); if (ret.size()) ret.pop(); } int top() { if (!siz()) return 0; while (!ret.empty() && !del.empty() && ret.top() == del.top()) ret.pop(), del.pop(); return ret.top(); } int setop() { if (siz() < 2) return 0; int x = top(); Pop(); int y = top(); push(x); return y; }} a[N], b[N], ans;struct Edge { int next, num;} e[N * 3];int n, tot, cnt, rt, now, c[N], d[N], f[N], p[N], dep[N], siz[N], vis[N], ff[N][20];vector
E[N];void add(int x, int y) { e[++cnt] = (Edge) {e[x].next, y}; e[x].next = cnt;}void getr(int x, int fa) { f[x] = 0, siz[x] = 1; for (int i = 0; i < E[x].size(); i++) { int k = E[x][i]; if (k == fa || vis[k]) continue; getr(k, x); chkmax(f[x], siz[k]); siz[x] += siz[k]; } chkmax(f[x], now - siz[x]); if (f[x] < f[rt]) rt = x;}void work(int x, int fa) { vis[x] = 1, p[x] = fa; if (fa) add(fa, x); for (int i = 0; i < E[x].size(); i++) { int k = E[x][i]; if (vis[k]) continue; f[rt = 0] = inf, now = siz[k]; getr(k, x); work(rt, x); }}void dfs(int x, int fa) { d[x] = d[fa] + 1; for (int i = 1; i <= 18; i++) ff[x][i] = ff[ff[x][i - 1]][i - 1]; for (int i = 0; i < E[x].size(); i++) { int k = E[x][i]; if (k == fa) continue; ff[k][0] = x; dfs(k, x); }}int lca(int x, int y) { if (d[x] < d[y]) swap(x, y); for (int i = 18; i >= 0; i--) if (d[ff[x][i]] >= d[y]) x = ff[x][i]; if (x == y) return x; for (int i = 18; i >= 0; i--) if (ff[x][i] != ff[y][i]) x = ff[x][i], y = ff[y][i]; return ff[x][0];}int dis(int x, int y) { int z = lca(x, y); return d[x] + d[y] - 2 * d[z];}void update(int x, int y, int z) { a[z].push(dis(x, y)); for (int p = e[x].next; p; p = e[p].next) update(e[p].num, y, z);}void getd(int x) { dep[x] = dep[p[x]] + 1; for (int p = e[x].next; p; p = e[p].next) getd(e[p].num);}void init() { f[rt = 0] = inf; dfs(1, 0); now = n; getr(1, 0); work(rt, 0); for (int i = 1; i <= n; i++) if (p[i]) update(i, p[i], i); for (int i = 1; i <= n; i++) { b[i].push(0); for (int p = e[i].next; p; p = e[p].next) { int k = e[p].num; if (a[k].siz()) b[i].push(a[k].top()); } } for (int i = 1; i <= n; i++) ans.push(b[i].top() + b[i].setop());}void Insert(Heap &a) { if (a.siz() >= 2) { int t = a.top() + a.setop(); ans.push(t); }}void Erase(Heap &a) { if (a.siz() >= 2) { int t = a.top() + a.setop(); ans.erase(t); }}void modify(int x) { if (c[x] == 1) { Erase(b[x]), b[x].push(0); Insert(b[x]); for (int y = x; p[y]; y = p[y]) { Erase(b[p[y]]); if (a[y].siz()) b[p[y]].erase(a[y].top()); a[y].push(dis(p[y], x)); if (a[y].siz()) b[p[y]].push(a[y].top()); Insert(b[p[y]]); } tot++; } else { Erase(b[x]); b[x].erase(0); Insert(b[x]); for (int y = x; p[y]; y = p[y]) { Erase(b[p[y]]); if (a[y].siz()) b[p[y]].erase(a[y].top()); a[y].erase(dis(p[y], x)); if (a[y].siz()) b[p[y]].push(a[y].top()); Insert(b[p[y]]); } tot--; } c[x] ^= 1;}int main() { read(n); cnt = tot = n; for (int i = 1; i < n; i++) { int x, y; read(x), read(y); E[x].push_back(y), E[y].push_back(x); } init(); int q; read(q); while (q--) { char c = getchar(); while (!isalpha(c)) c = getchar(); if (c == 'C') { int x; read(x); modify(x); } else if (tot < 2) cout << tot - 1 << "\n"; else cout << ans.top() << "\n"; } return 0;}

转载于:https://www.cnblogs.com/copperoxide/p/9476776.html

你可能感兴趣的文章
oracle 应用程序调用存储函数
查看>>
洛谷 P3629 [APIO2010]巡逻 解题报告
查看>>
Fedora 23+CUDA 8.0+ GTX970 安装
查看>>
在Visual Studio中开发一个C语言程序
查看>>
课程总结
查看>>
openstack新建虚机、网络、路由时候对应的ovs网桥的变化
查看>>
linux 编译运行c文件
查看>>
Scrapy的学习和使用
查看>>
7.内部类(一)之详解内部类
查看>>
1.messager消息提示框
查看>>
[PY]进制转换
查看>>
STL系列 list
查看>>
匿名方法和Lambda表达式
查看>>
京东的核心业务
查看>>
读书笔记(六)--成交
查看>>
Secret Number hdu 2113
查看>>
软件架构(体系结构,Architecture)和软件框架
查看>>
阶梯博弈(没怎么搞懂)
查看>>
python request post请求body中有json数组
查看>>
IDT hook KiTrap03
查看>>