文章目录

  • title
  • solution
  • code

title

solution

一棵nnn个点的树有n−1n-1n−1条边。

一般的,对于森林而言则有点数-边数=树的个数

那么我们将无向图随便生成一个生成树,形成森林。

询问的连通块的个数就变为求森林的树的个数,即森林的点数 n −-− 森林的边数 === 连通块的个数

然后就可以用LCTLCTLCT动态维护生成树了,将询问的 rrr 从小到大排序,主席树维护每条边是否在当前的生成树森林中出现。

在第 rrr 个版本的主席树中查 [l,r][l,r][l,r] 这段区间有多条边存在,这就是生成树森林的总边数。

LCTLCTLCT不好维护边权,建虚点连边即可。

对于[l,r][l,r][l,r]包含的边,假设就用先后输入的时间决定先后。

对于边iii,加入后若不能形成环,则直接加入;若形成环了,删掉环上最早的边
这样越往后的边越有可能存在于[l,r][l,r][l,r],rrr是递增的嘛。

所以正确性也是可以保障的。

⚡:有自环哦!

code

#include <cstdio>
#include <iostream>
using namespace std;
#define maxn 400005
#define inf 0x7f7f7f7f
struct node {int u, v;
}edge[maxn];struct LCT {int f, rev, val, minn;int son[2];
}tree[maxn];
int st[maxn];bool notroot( int x ) {return tree[tree[x].f].son[0] == x || tree[tree[x].f].son[1] == x;
}void update( int x ) {tree[x].minn = min( tree[x].val, min( tree[tree[x].son[0]].minn, tree[tree[x].son[1]].minn ) );
}void reverse( int x ) {swap( tree[x].son[0], tree[x].son[1] );tree[x].rev ^= 1;
} void pushdown( int x ) {if( ! tree[x].rev ) return;reverse( tree[x].son[0] );reverse( tree[x].son[1] );tree[x].rev = 0;
}void rotate(int x) { int fa = tree[x].f, Gfa = tree[fa].f;int k = tree[fa].son[1] == x;if( notroot( fa ) )tree[Gfa].son[tree[Gfa].son[1] == fa] = x;tree[x].f = Gfa;tree[fa].son[k] = tree[x].son[k ^ 1];if( tree[x].son[k ^ 1] )tree[tree[x].son[k ^ 1]].f = fa;tree[x].son[k ^ 1] = fa;tree[fa].f = x;update( fa );update( x );
}void splay( int x ) {int top = 0, y = x;st[++ top] = y;while( notroot( y ) ) st[++ top] = y = tree[y].f;while( top ) pushdown( st[top --] );while( notroot( x ) ) {int fa = tree[x].f, Gfa = tree[fa].f;if( notroot( fa ) ) ( ( tree[Gfa].son[0] == fa ) ^ ( tree[fa].son[0] == x ) ) ? rotate( x ) : rotate( fa );rotate( x );}update( x );
}void access( int x ) {for( int son = 0;x;son = x, x = tree[x].f ) {splay( x );tree[x].son[1] = son;update( x );}
}void makeroot( int x ) {access( x );splay( x );swap( tree[x].son[0], tree[x].son[1] );tree[x].rev ^= 1;
}void split( int x, int y ) {makeroot( x );access( y );splay( y );
}int findroot( int x ) {access( x );splay( x );while( tree[x].son[0] ) x = tree[x].son[0];splay( x );return x;
}void link( int x, int y ) {split( x, y );tree[x].f = y;
}void cut( int x, int y ) {split( x, y );tree[x].f = tree[y].son[0] = 0;
}int ask( int x, int y ) {split( x, y );return tree[y].minn;
}struct SegmentTree {int cnt, l, r;
}seg[maxn * 20];
int tot;
int rt[maxn];void modify( int &num, int l, int r, int pos, int v ) {int x = ++ tot;seg[x].l = seg[num].l, seg[x].r = seg[num].r, seg[x].cnt = seg[num].cnt + v, num = x;if( l == r ) return;int mid = ( l + r ) >> 1;if( pos <= mid ) modify( seg[num].l, l, mid, pos, v );else modify( seg[num].r, mid + 1, r, pos, v );
}int query( int num, int l, int r, int L, int R ) {if( L <= l && r <= R ) return seg[num].cnt;int mid = ( l + r ) >> 1, ans = 0;if( L <= mid ) ans += query( seg[num].l, l, mid, L, R );if( mid < R ) ans += query( seg[num].r, mid + 1, r, L, R );return ans;
}int n, m, Q, t, last;void get( int &l, int &r ) {if( t ) l = ( l + last ) % m + 1, r = ( r + last ) % m + 1; if( l > r ) swap( l, r );
}int main() {scanf( "%d %d %d %d", &n, &m, &Q, &t );for( int i = 0;i <= n;i ++ ) tree[i].val = tree[i].minn = inf;for( int i = 1;i <= m;i ++ ) {scanf( "%d %d", &edge[i].u, &edge[i].v );tree[i + n].val = tree[i + n].minn = i;}for( int i = 1;i <= m;i ++ ) {int u = edge[i].u, v = edge[i].v;rt[i] = rt[i - 1];if( u == v ) continue;modify( rt[i], 1, m, i, 1 );if( findroot( u ) == findroot( v ) ) {int pos = ask( u, v );cut( edge[pos].u, pos + n );cut( edge[pos].v, pos + n );modify( rt[i], 1, m, pos, -1 );}link( u, i + n );link( v, i + n );}while( Q -- ) {int l, r;scanf( "%d %d", &l, &r );get( l, r );last = n - query( rt[r], 1, m, l, r );printf( "%d\n", last );}return 0;
}

[Cnoi2019]须臾幻境(LCT维护最大生成树+主席树/分块)相关推荐

  1. BZOJ3514 Codechef MARCH14 GERALD07加强版 LCT维护最大生成树 主席树

    题面 考虑没有询问,直接给你一个图问联通块怎么做. 并查集是吧. 现在想要动态地做,那么应该要用LCT. 考虑新加进来一条边,想要让它能够减少一个联通块的条件就是现在边的两个端点还没有联通. 如果联通 ...

  2. bzoj 4736: 温暖会指引我们前行 (LCT 维护最大生成树)

    链接:https://www.lydsy.com/JudgeOnline/problem.php?id=4736 题面: 寒冬又一次肆虐了北国大地 无情的北风穿透了人们御寒的衣物 可怜虫们在冬夜中发出 ...

  3. HDU 2852 KiKi's K-Number 主席树

    题意: 要求维护一个数据结构,支持下面三种操作: \(0 \, e\):插入一个值为\(e\)的元素 \(1 \, e\):删除一个值为\(e\)的元素 \(2 \, a \, k\):查询比\(a\ ...

  4. CodeForces - 916D Jamie and To-do List(主席树+模拟)

    题目链接:点击查看 题目大意:模拟实现 nnn 次操作,每次操作共有四种类型: setaixiset \ a_i \ x_iset ai​ xi​:设置 aia_iai​ 的优先级为 xix_ixi​ ...

  5. 模板三连击:树状数组+线段树+主席树

    没事儿干,复习模板...... 1.树状数组 本来不想写这个的,但是反正就几分钟就打完了,所以就写了,水AC数. 洛谷 P3374 [模板]树状数组 1 1 #include<cstdio> ...

  6. BZOJ1901 Zju2112 Dynamic Rankings 【树状数组套主席树】

    题目 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]--a[j]中第k小的数是多少(1≤k≤j- ...

  7. 【洛谷P5385】须臾幻境/【BZOJ3514】Codechef MARCH14 GERALD07加强版【LCT】【主席树】

    题意:有nnn个点mmm条边,qqq次询问连接区间[L,R][L,R][L,R]中的边后的连通块个数.强制在线. n,m,q≤2×105n,m,q\leq 2\times10^5n,m,q≤2×105 ...

  8. LOJ 121 「离线可过」动态图连通性——LCT维护删除时间最大生成树 / 线段树分治...

    题目:https://loj.ac/problem/121 离线,LCT维护删除时间最大生成树即可.注意没有被删的边的删除时间是 m+1 . 回收删掉的边的节点的话,空间就可以只开 n*2 了. #i ...

  9. bzoj3514(LCT+主席树)

    题目描述 N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数. 题解 对于一个截止时间来说,越晚的变越好. 所以我们可以维护一颗以边的序号为关键字的最大生成树,然后用主席树维 ...

最新文章

  1. 写一个android图表框架1
  2. 赤兔四足机器人的作用_跑得快,打不死!清华大学开发“小强”机器人,壮汉狂踩也挡不住前进步伐...
  3. 快速启动神器 Wox
  4. AOJ 491.扑克牌
  5. Java 中初始化 List 集合的 6 种方式!
  6. 098 Validate Binary Search Tree 验证二叉搜索树
  7. PHP编程最快明白 by www.kuphp.com 案例实战zencart1.38a支付模块简化Fast and Easy Checkout配置...
  8. 魔兽嘉年华,云信四大码魔与你不见不散
  9. 瑞银监控机器人组装法_瑞银公布Model 3后续拆解报告:装配问题严重 噪音勉强能接受...
  10. TypeScript里的类型合并操作符
  11. HDFS balancer 异常处理
  12. 水环境模型与大数据技术融合研究
  13. ASP.NET页面与IIS底层交互和工作原理详解(一)
  14. Linux Ubuntu 内核升级
  15. python笔记——常用的内置函数
  16. 【ArcGIS操作】2 高级编辑篇
  17. 为什么mfc要注册WNDCLASS样式
  18. Acer 4750 安装黑苹果_黑苹果安装 你要知道的那些坑
  19. 三星香港 android8.0,三星On7官方港版安卓8.0固件rom线刷包:TGY-G6100ZHU3CSG1
  20. IE浏览器闪退、自动打开Edge浏览器

热门文章

  1. data:text/html firefox钓鱼,JS DataURL 整理(一)
  2. excel 如何替换带上标的文字_如何在Excel中批量提取中文汉字和英文字母
  3. 30屏幕参数_顶级屏幕加持,一加8系列核心配置、屏幕参数官方公布
  4. java线程带来的异常,java多线程练习之捕获子线程异常例子
  5. 山东大学计算机非全上课,山东大学非全日制研究生上课方式
  6. 昆明学院计算机二级报名时间,2017年3月昆明学院计算机等级考试报名时间(云南)...
  7. 获取html滚动条位置,pc和移动端获取滚动条的位置
  8. 后端学习 - 计算机网络
  9. leetcode232. 用栈实现队列
  10. 35. 搜索插入位置011(二分查找)