51Nod-1618-树或非树
来源:互联网 发布:mac 建筑 软件 收费吗 编辑:程序博客网 时间:2024/05/21 22:44
ACM模版
描述
题解
这是
大佬题解:
这个题解的第一句我无法理解,题目中说给定一个 一棵树 + 一条边
啊,这么强的条件,我不理解该大佬从何悟出,难道说是因为数据太水了,误打误撞的吗?这个问题我纠结了一天,怎么想也想不通为何得出这样的结论,当然,如果是建立在这个强条件下,那么后边的题解就很容易理解了。
代码
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int MAXN = 100005;int n, m;int cnt1, cnt2, tmp, mb, mdb, ans;int d[MAXN], z[MAXN], g[MAXN], o[MAXN];int pre[MAXN], pre_[MAXN], p[MAXN << 1], nxt[MAXN << 1];struct node{ int g, cnt; int l[MAXN], r[MAXN]; int z[MAXN], a[MAXN]; int x[MAXN], y[MAXN]; int pre[MAXN], root[MAXN]; void put(int i, int j) { if (i && j) { z[i] = !z[i]; a[i] = !a[i]; swap(x[i], y[i]); } } void lazy(int i) { put(l[i], z[i]); put(r[i], z[i]); z[i] = 0; } void rt(int i, int j) { if (l[i] == j) { l[i] = r[j]; pre[r[j]] = i; r[j] = i; } else { r[i] = l[j]; pre[l[j]] = i; l[j] = i; } root[j] = root[i]; root[i] = 0; if (l[pre[i]] == i) { l[pre[i]] = j; } else if (r[pre[i]] == i) { r[pre[i]] = j; } pre[j] = pre[i]; pre[i] = j; update(i); update(j); } void splay(int i, int j) { if (root[i]) { lazy(i); } while (!root[i]) { lazy(pre[i]); lazy(i); rt(pre[i], i); } if (j) { root[g = r[i]] = 1; r[i] = 0; update(i); } } void update(int i) { x[i] = x[l[i]] + x[r[i]] + a[i]; y[i] = y[l[i]] + y[r[i]] + 1 - a[i]; } void access(int i) { splay(cnt = i, 1); while (pre[i]) { splay(cnt = pre[i], 1); r[cnt] = 1; rt(cnt, i); } } void cover(int i) { access(i); splay(tmp, 0); ans += y[r[tmp]] - x[r[tmp]]; put(r[tmp], 1); }} tree;void link(int a, int b){ nxt[++cnt1] = d[a]; d[a] = cnt1; p[cnt1] = b;}int find(int i){ return (pre_[i] == i) ? i : pre_[i] = find(pre_[i]);}void dfs1(int i, int h){ z[++cnt1] = i; o[i] = cnt1; for (int k = d[i], j = p[k]; k; k = nxt[k], j = p[k]) { if ((h ^ k) != 1) { if (o[j]) { mb = k; for (int l = o[j]; l <= cnt1; l++) { g[++cnt2] = z[l]; } } else { dfs1(j, k); } } } cnt1--;}void dfs2(int i, int h){ for (int k = d[i], j = p[k]; k; k = nxt[k], j = p[k]) { if ((h ^ k) != 1 && ((k ^ mb) > 1)) { pre[j] = i; dfs2(j, k); } }}template <class T>inline void scan_d(T &ret){ char c; ret = 0; while ((c = getchar()) < '0' || c > '9'); while (c >= '0' && c <= '9') { ret = ret * 10 + (c - '0'), c = getchar(); }}int main(){ scan_d(n); scan_d(m); cnt1 = 1; int a, b, mdb = 0; for (int i = 1; i <= n; i++) { scan_d(a); scan_d(b); link(a, b); link(b, a); } cnt1 = 0; dfs1(1, 0); dfs2(g[1], 0); for (int i = 0; i < MAXN; i++) { o[i] = 0; } for (int i = 1; i <= cnt2; i++) { o[g[i]] = i; } for (int i = 1; i <= n; i++) { pre_[i] = (o[i]) ? i : pre[i]; } for (int i = 1; i <= n; i++) { find(i); } for (int i = 1; i <= n; i++) { tree.pre[i] = pre[i]; tree.y[i] = tree.root[i] = 1; } g[0] = g[cnt2]; tmp = g[cnt2 + 1] = g[1]; while (m--) { scan_d(a); scan_d(b); int Fa = pre_[a], Fb = pre_[b]; int d1 = abs(o[Fa] - o[Fb]); int g1, g2; if (o[Fa] < o[Fb]) { g1 = g[o[Fa] + 1]; g2 = g[o[Fa] - 1]; } else { g1 = g[o[Fa] - 1]; g2 = g[o[Fa] + 1]; } tree.cover(a); tree.cover(b); if (d1 > cnt2 - d1 || ((d1 == cnt2 - d1) && g1 > g2)) { mdb = !mdb; if (mdb) { ans++; } else { ans--; } tree.cover(g[cnt2]); } tree.access(g[cnt2]); int al = tree.x[g[cnt2]] + mdb == cnt2; printf("%d\n", n - ans + al); } return 0;}
阅读全文
0 0
- 51Nod-1618-树或非树
- 51nod 1618 树或非树 树链剖分+线段树
- 51nod 1628 非波那契树 (倍增)
- 51NOD 非010串
- 51Nod-1523-非回文
- 51NOD 1523 非回文
- 51NOD 1523 非回文
- 51nod 1523 非回文
- 51nod-1523 非回文
- 51nod 1523 非回文
- 51nod 异或凑数
- 51Nod-1353-树
- 51nod 1668 非010串
- 51nod 1523 非回文(DFS)
- 51nod 1577 异或凑数
- 51nod 1577 异或凑数
- 51nod 1312 最大异或和
- 51nod 1312 最大异或和
- Python NLP入门教程
- nova的pause instance的log
- java基础---------字符串常量池-创建了几个对象
- TCP/IP--ICMP和IGMP
- tensorflow 模型训练
- 51Nod-1618-树或非树
- 数据结构与算法--关键路径
- 文字一行显示,超出部分显示省略号
- js基础知识
- orcl 查询锁表 解锁
- 在串口禁止打印内核信息
- VUE 页面的跳转写法
- 字符串大小写转换及省略其中数字输出
- Scaffolding Template on Asp.Net Core Razor Page