题意

给出nnn个点,mmm条边.多次询问,求编号在[l,r][l,r][l,r]内的边形成的联通块的数量,强制在线.

分析

  • LCTLCTLCT维护动态最大生成树,先将每条边依次加进去,若形成环就断掉最早加进去(编号最小)的边,然后记录early[]early[]early[]数组,表示第i条边弹掉了哪条边,若没有弹出边,early[i]=0early[i]=0early[i]=0
  • 然后每个询问的答案就是用n减掉[l,r]区间内early值小于l的边的数量,可以用主席树来维护
  • 正确性证明:因为是维护的最大生成树,而early[i]early[i]early[i]又是最大生成树中的最小边,那么(early[i],i)(early[i],i)(early[i],i)这些边一定不能让iii的两个端点联通.所以说对于r>=ir>=ir>=i且l>early[i]l>early[i]l>early[i]的询问,如果按编号从小到大加入边,那么在iii之前它的两个端点一定还不联通,加入iii这条边让它们合并成为一个联通块,答案就减一.所以说只要求出所有earlyearlyearly在主席树上维护就行了.
  • 注意有自环(良心样例有自环)

CODE

#include <cctype>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
char cb[1<<15],*cs=cb,*ct=cb;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<15,stdin),cs==ct)?0:*cs++)
template<class T>inline void read(T &res) {
char ch; for(;!isdigit(ch=getc()););
for(res=ch-'0';isdigit(ch=getc());res=res*10+ch-'0');
}
const int MAXN = 200005;
const int MAXM = MAXN*20;
int n;
namespace LCT {
const int N = 400005;
#define ls ch[x][0]
#define rs ch[x][1]
int ch[N][2], fa[N], mn[N]; bool rev[N];
inline bool isr(int x) { return ch[fa[x]][0] != x && ch[fa[x]][1] != x; }
inline bool get(int x) { return ch[fa[x]][1] == x; }
inline int Max(int x, int y) { if(x <= n) return y; if(y <= n) return x; return min(x, y); }
inline void upd(int x) { mn[x] = Max(x, Max(mn[ls], mn[rs]));}
inline void mt(int x) { if(rev[x]) rev[x]^=1, rev[ls]^=1, rev[rs]^=1, swap(ls, rs); }
void mtpath(int x) { if(!isr(x)) mtpath(fa[x]); mt(x); }
inline void rot(int x) {
int y = fa[x], z = fa[y];
bool l = get(x), r = l^1;
if(!isr(y)) ch[z][get(y)] = x;
fa[ch[x][r]] = y, fa[y] = x, fa[x] = z;
ch[y][l] = ch[x][r], ch[x][r] = y;
upd(y), upd(x);
}
inline void splay(int x) {
mtpath(x);
for(; !isr(x); rot(x))
if(!isr(fa[x])) rot(get(x) == get(fa[x]) ? fa[x] : x);
}
inline int access(int x) { int y = 0;
for(; x; x = fa[y=x]) splay(x), ch[x][1] = y, upd(x);
return y;
}
inline void bert(int x) { access(x), splay(x), rev[x]^=1; }
inline int sert(int x) { access(x), splay(x); for(; ls; x=ls); return x; }
inline bool judge(int x, int y) { bert(x); return sert(y) == x; }
inline void link(int x, int y) { bert(x); fa[x] = y; }
inline void split(int x, int y) { bert(x); access(y), splay(y); }
inline void cut(int x, int y) { split(x, y); ch[y][0] = fa[x] = 0; upd(y); }
inline int findmn(int x, int y) { split(x, y); return mn[y]; }
#undef ls
#undef rs
}
int m, q, type, pre[MAXN], u[MAXN], v[MAXN];
int rt[MAXN], sz, sum[MAXM], ch[MAXM][2];
void modify(int &i, int p, int l, int r, int x) {
if(!i) i = ++sz;
sum[i] = sum[p] + 1;
if(l == r) return;
int mid = (l + r) >> 1;
if(x <= mid) ch[i][1] = ch[p][1], modify(ch[i][0], ch[p][0], l, mid, x);
else ch[i][0] = ch[p][0], modify(ch[i][1], ch[p][1], mid+1, r, x);
}
int query(int i, int j, int l, int r, int ql, int qr) {
if(l == ql && r == qr) return sum[j] - sum[i];
int mid = (l + r) >> 1;
if(qr <= mid) return query(ch[i][0], ch[j][0], l, mid, ql, qr);
else if(ql > mid) return query(ch[i][1], ch[j][1], mid+1, r, ql, qr);
return query(ch[i][0], ch[j][0], l, mid, ql, mid) + query(ch[i][1], ch[j][1], mid+1, r, mid+1, qr);
}
int main () {
read(n), read(m), read(q), read(type);
for(int i = 1; i <= m; ++i) {
read(u[i]), read(v[i]);
if(u[i] == v[i]) rt[i] = rt[i-1];
else {
if(LCT::judge(u[i], v[i])) {
int p = LCT::findmn(u[i], v[i]);
pre[i] = p-n;
LCT::cut(u[pre[i]], p);
LCT::cut(v[pre[i]], p);
}
LCT::link(u[i], n+i);
LCT::link(v[i], n+i);
modify(rt[i], rt[i-1], 0, m, pre[i]);
}
}
int lastans = 0, x, y;
while(q--) {
read(x), read(y);
if(type) x ^= lastans, y ^= lastans;
printf("%d\n", lastans = (n - query(rt[x-1], rt[y], 0, m, 0, x-1)));
}
}

BZOJ 3514: Codechef MARCH14 GERALD07加强版 (LCT维护最大生成树+主席树)的更多相关文章

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

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

  2. BZOJ 3514: Codechef MARCH14 GERALD07加强版( LCT + 主席树 )

    从左到右加边, 假如+的边e形成环, 那么记下这个环上最早加入的边_e, 当且仅当询问区间的左端点> _e加入的时间, e对答案有贡献(脑补一下). 然后一开始是N个连通块, 假如有x条边有贡献 ...

  3. BZOJ 3514: Codechef MARCH14 GERALD07加强版 [LCT 主席树 kruskal]

    3514: Codechef MARCH14 GERALD07加强版 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 1312  Solved: 501 ...

  4. [BZOJ 3514]Codechef MARCH14 GERALD07加强版 (CHEF AND GRAPH QUERIES)

    [BZOJ3514] Codechef MARCH14 GERALD07加强版 (CHEF AND GRAPH QUERIES) 题意 \(N\) 个点 \(M\) 条边的无向图,\(K\) 次询问保 ...

  5. BZOJ 3514: Codechef MARCH14 GERALD07加强版(LCT + 主席树)

    题意 \(N\) 个点 \(M\) 条边的无向图,询问保留图中编号在 \([l,r]\) 的边的时候图中的联通块个数. \(K\) 次询问强制在线. \(1\le N,M,K \le 200,000\ ...

  6. 【刷题】BZOJ 3514 Codechef MARCH14 GERALD07加强版

    Description N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数. Input 第一行四个整数N.M.K.type,代表点数.边数.询问数以及询问是否加密. 接下来 ...

  7. BZOJ 3514 Codechef MARCH14 GERALD07加强版 Link-Cut-Tree+划分树

    题目大意: 给定n个点m条边的无向图.求问当图中仅仅有[编号在[l,r]区间内]的边存在时图中的联通块个数 强制在线 注意联通块是指联通了就是同一块,不是Tarjan求的那种块 看到这题的那一刻我就想 ...

  8. BZOJ 3514 Codechef MARCH14 GERALD07加强版

    题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3514 题意:给出一个图m条边.每次询问只加入编号在区间[L,R]之内的边有多少连通 ...

  9. [BZOJ3514]CodeChef MARCH14 GERALD07加强版(LCT+主席树)

    3514: Codechef MARCH14 GERALD07加强版 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 2177  Solved: 834 ...

随机推荐

  1. 如何配置虚拟机的ip地址以及如何使用XShell和WinSCP工具

    参考资料:https://blog.csdn.net/phy1997/article/details/78928796

  2. 和HTTP相关的web服务器内容

    一台web服务器可以搭建多个独立域名的网站,也可以作为通信路径上的中转服务器提升传输效率. 1. 用单台虚拟主机实现多个域名 多个域名解析后对应的ip地址相同,需要在Host首部中包含完整的主机名或者 ...

  3. selenium登录实验楼

    from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.s ...

  4. python 修改文件的创建时间、修改时间、访问时间

    目录 python 修改文件创建.修改.访问时间 方案一 方案二(无法修改文件创建时间) python 修改文件创建.修改.访问时间 突如其来想知道一下 python 如何修改文件的属性(创建.修改. ...

  5. golang数据基本数据类型和string类型的转换

    基本类型之间的转换 golang在不同类型的变量之间赋值时需要显式转换,也就是说golang中数据类型不能自动转换. 表达式T(v)将值v转换为类型T 1.数据类型的转换可以是从范围小——>范围 ...

  6. 一个MySQL JDBC驱动bug引起的血案

    1.1      问题背景 公司是做电商系统的,整个系统搭建在华为云上.系统设计的时候,考虑到后续的用户和订单数量比较大,需要使用一些大数据库的组件.关系型数据库这块,考虑到后续数据量的快速增长,不是 ...

  7. Lua模除运算的大坑

    问题 对负数进行模除运算遇到的坑,Lua的%运算与C++的%有差异 实践 结论 Lua%运算的基本公式 a % b = a - ( ( a // b ) * b ) 1.在C,C++中 %运算符的取整 ...

  8. Guide 哥:有哪些程序员受用一生的好习惯?

    本文来自 Guide 哥开源的 Github 仓库 programmer-advancement:https://github.com/Snailclimb/programmer-advancemen ...

  9. 怎样在浏览器端增加一条Cookie

    可以使用 document.cookie, 这个属性可读可写, 读时是读取所有没有设置HttpOnly的cookie作为一个字符串返回, 写时是将一个cookie写入到document.cookie中 ...

  10. Java装饰者模式(思维导图)

    图1 装饰者模式[点击查看图片] 1,一个简单的以人为主体的装饰者模式 被装饰者 public interface Human {//被装饰者 public void wearClothes(); p ...