【GDOI2018模拟9.23】动态图
来源:互联网 发布:软件研发部门规划 编辑:程序博客网 时间:2024/05/22 07:07
Description:
1<=n<=10^6,1<=q<=200000
题解:
暴力可以用按秩合并并查集,这个数据结构支持删除。
对于正解,我们需要把l->r条边一次加进并查集,对于每一条边,它有贡献,就是加入它的时候,它会合并两个不同的集合。
反过来,它没有贡献,就是它所连着的两端本来就在一个集合里。
假设我们按1->r的顺序加入每一条边,当加入一条边时,设它是x,y,设z为x到y的路径上编号最小的边(x,y不在一个集合里是0)的编号,那么如果有询问包含这条边,且左端点小于等于z,那么当前这条边就是没有贡献的,否则它就是有贡献。
于是用lct维护一棵最大生成树,就可以求出z,再用主席树随便维护一下就行了。
Code:
#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#define fo(i, x, y) for(int i = x; i <= y; i ++)#define min(a, b) ((a) < (b) ? (a) : (b))using namespace std;const int N = 1000000, M = 200005;int n, q, type, tt, u, v, l, r, ans, m;int t[N + M][2], fa[N + M], pf[N + M], rev[N + M], mi[N + M], dd[N + M];int g[N + M], tot;struct tree{ int l, r, s;}d[N * 10];struct edge { int u, v, x, y, z;}e[N + M];int last[N + M];int lr(int x) {return t[fa[x]][1] == x;}void chan(int x) {if(x) swap(t[x][0], t[x][1]), rev[x] ^= 1;}void down(int x) {if(x && rev[x]) chan(t[x][0]), chan(t[x][1]), rev[x] = 0;}void update(int x) { if(!x) return; mi[x] = min(mi[t[x][0]], mi[t[x][1]]); if(x > N) mi[x] = min(mi[x], x - N);}void xc(int x) { for(; x; x = fa[x]) dd[++ dd[0]] = x; for(; dd[0]; dd[0] --) down(dd[dd[0]]);}void rotate(int x) { int y = fa[x], k = lr(x); t[y][k] = t[x][!k]; if(t[x][!k]) fa[t[x][!k]] = y; fa[x] = fa[y]; if(fa[y]) t[fa[y]][lr(y)] = x; t[x][!k] = y; fa[y] = x; pf[x] = pf[y]; update(y); update(x);}void splay(int x, int y) { xc(x); while(fa[x] != y) { if(fa[fa[x]] != y) if(lr(x) == lr(fa[x])) rotate(fa[x]); else rotate(x); rotate(x); }}void dg(int x) { if(x == 0) return; down(x); printf("%d %d %d %d tree\n", x, mi[x], t[x][0], t[x][1]); dg(t[x][0]); dg(t[x][1]);}void access(int x) { int y = 0; while(x) { splay(x, 0); fa[t[x][1]] = 0; pf[t[x][1]] = x; t[x][1] = y; fa[y] = x; pf[y] = 0; update(x); y = x; x = pf[x]; } }void makeroot(int x) { access(x); splay(x, 0); chan(x);}void link(int x, int y) { makeroot(x); pf[x] = y; access(x);}void cut(int x, int y) { makeroot(x); access(y); splay(y, 0); t[y][0] = fa[x] = pf[x] = 0; update(y);}int find_z(int x) { down(x); return t[x][0] == 0 ? x : find_z(t[x][0]);}int pd(int x, int y) { makeroot(x); access(y); splay(y, 0); return find_z(y) == x;}void change(int i, int x, int y, int l, int r) { if(x == y) { d[i].s += r; return; } int m = (x + y) >> 1; d[++ tot] = d[d[i].l], d[i].l = tot; d[++ tot] = d[d[i].r], d[i].r = tot; if(l <= m) change(d[i].l, x, m, l, r); else change(d[i].r, m + 1, y, l, r); d[i].s = d[d[i].l].s + d[d[i].r].s;}int find(int i, int x, int y, int l, int r) { if(i == 0) return 0; if(x == l && y == r) return d[i].s; int m = (x + y) >> 1; if(r <= m) return find(d[i].l, x, m, l, r); else if(l > m) return find(d[i].r, m + 1, y, l, r); else return find(d[i].l, x, m, l, m) + find(d[i].r, m + 1, y, m + 1, r);}const int Mm = 200000;void xiu(int m, int last) { g[m] = ++ tot; d[g[m]] = d[g[m - 1]]; change(g[m], 0, Mm, last, 1);}int qiu(int l, int r) { return find(g[r], 0, Mm, 0, l - 1) - find(g[l - 1], 0, Mm, 0, l - 1);}int main() { freopen("graph.in", "r", stdin); freopen("graph.out", "w", stdout); scanf("%d %d %d", &n, &q, &type); fo(i, 0, N) mi[i] = 1e9; g[0] = tot = 1; fo(Q, 1, q) { scanf("%d", &tt); if(tt == 1) { scanf("%d %d", &u, &v); if(type) u = (u ^ ans) % n + 1; if(type) v = (v ^ ans) % n + 1; e[++ m].u = u, e[m].v = v; if(u == v) { last[m] = m; xiu(m, m); continue; } if(pd(u, v)) { makeroot(u); access(v); splay(v, 0); int z = mi[v]; e[m].x = e[z].u; e[m].y = e[z].v; e[m].z = z; cut(e[m].x, e[m].z + N); cut(e[m].y, e[m].z + N); link(u, m + N); link(v, m + N); last[m] = z; xiu(m, z); } else { link(u, m + N); link(v, m + N); last[m] = 0; xiu(m, 0); } } else if(tt == 2) { if(e[m].u == e[m].v) { m --; continue; } if(last[m]) { cut(e[m].u, m + N); cut(e[m].v, m + N); link(e[m].x, e[m].z + N); link(e[m].y, e[m].z + N); } else { cut(e[m].u, m + N); cut(e[m].v, m + N); } m --; } else { scanf("%d %d", &l, &r); if(type) l = (l ^ ans) % m + 1; if(type) r = (r ^ ans) % m + 1; if(l > r) swap(l, r); ans = n - qiu(l, r); printf("%d\n", ans); } }}
阅读全文
0 0
- 【GDOI2018模拟9.23】动态图
- 【GDOI2018模拟9.23】动态图
- JZOJ 5387【GDOI2018模拟9.23】动态图
- 【GDOI2018模拟9.23】博弈
- 【jzoj5219】【GDOI2018模拟7.10】【B】【动态规划】
- 【GDOI2018模拟7.10】B 动态规划
- 【GDOI2018模拟7.10】C 动态规划
- 【jzoj5220】【GDOI2018模拟7.10】【C】【动态规划】
- 【GDOI2018模拟8.7】图的异或
- bzoj 5220. 【GDOI2018模拟7.10】C 动态规划
- bzoj 5223. 【GDOI2018模拟7.12】B 动态规划+矩阵乘法
- 【jzoj5237】【GDOI2018模拟8.7】【最长公共子序列 】【动态规划】
- 【jzoj5251】【GDOI2018模拟8.11】【决战】【状态压缩动态规划】
- 【GDOI2018模拟7.6】吃干饭
- 【GDOI2018模拟7.9】期末考试
- 【GDOI2018模拟7.8】质数
- 【GDOI2018模拟7.8】矩阵
- 【GDOI2018模拟7.10】B
- 关于项目的一点点总结,签到返利日历的实现
- CAN通信中地址设置的问题
- $.Deferred(),for循环内异步请求问题的解决办法
- 三个字符串s1, s2, s3, 现要求你判断s3是否由s1和s2交错组成的
- 1004: A+B(基本输入输出4)
- 【GDOI2018模拟9.23】动态图
- mysql忘记root密码如何解决(mac电脑)
- 关于AsyncTask的Executor的一些研究
- 1094: 【白书习题】数的反转
- latex: 改变图的caption Figure 1:为 Fig. 1.
- ffmpeg安装及简单使用
- CentOS 6.7安装Docker
- 1008: C基础-公约公倍
- 转:Opencv高斯滤波函数分析