Code Chef - Chef and Graph Queries
题目大意
给定一个$n$个点$m$条边的无向图$(n,m\leq 200000)$。
有$q$每次询问$(q\leq 200000)$,每次给定一个区间$L,R$,求仅保留编号$\in[L,R]$的边,原图连通块的数量。
题解
不难发现连通块数量可以通过总点数$-$最大生成森林的边集大小得到。
按照编号对边从小到大排序,用$LCT$动态维护最大生成森林,每次操作加边时,若两个点不连通,就直接连边即可。
否则,就把路径上编号最小的边断掉,再强行连上新的边。则当前的生成森林一定是最大的并且恰好覆盖了每一个连通块。
对于每一次询问,就是用$n$减去在最大的边编号为$R$时,最大生成森林中编号$\in[L,R]$的数量。
用主席树维护一下即可。复杂度$O((m+q)\log n)$。
由于在$LCT$中维护边权比较复杂,所以我们可以把一条边变成一个点,这个点连向原边的两段端点,点权即为边权,会方便许多。
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define M 400020
#define INF 3000020
#define ls c[x][0]
#define rs c[x][1]
#define mid ((l+r)>>1)
using namespace std;
int read(){
int nm=0,fh=1; char cw=getchar();
for(;!isdigit(cw);cw=getchar()) if(cw=='-') fh=-fh;
for(;isdigit(cw);cw=getchar()) nm=nm*10+(cw-'0');
return nm*fh;
}
void write(int x){if(x>9) write(x/10);putchar(x%10+'0');}
int n,m,fa[M],c[M][2],u[M],v[M],e[M],rev[M];
int L[M*30],R[M*30],sum[M*30],cnt,rt[M],S[M],top,tot;
void pushup(int x){if(x) e[x]=(x>n?x-n:INF),e[x]=min(e[x],min(e[ls],e[rs]));}
void pushdown(int x){if(rev[x]&&x) rev[x]=0,rev[ls]^=1,rev[rs]^=1,swap(ls,rs);}
bool isroot(int x){return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;}
void rotate(int x){
int tp=fa[x],dtp=fa[fa[x]],ms,ds;
if(c[dtp][0]==tp) c[dtp][0]=x;
else if(c[dtp][1]==tp) c[dtp][1]=x;
if(c[tp][0]==x) ms=0,ds=1;else ms=1,ds=0;
fa[x]=dtp,fa[tp]=x,fa[c[x][ds]]=tp;
c[tp][ms]=c[x][ds],c[x][ds]=tp;
pushup(tp),pushup(x);
}
void splay(int x){
S[top=1]=x;
for(int y=x;!isroot(y);y=fa[y]) S[++top]=fa[y];
while(top) pushdown(S[top]),top--;
while(!isroot(x)){
int tp=fa[x];
if(isroot(tp)) return rotate(x);
else if(c[c[fa[tp]][0]][0]==x) rotate(tp);
else if(c[c[fa[tp]][1]][1]==x) rotate(tp);
else rotate(x);
}
}
int fdrt(int x){return fa[x]?fdrt(fa[x]):x;}
void access(int x){for(int y=0;x;y=x,x=fa[x]) splay(x),rs=y,pushup(x);}
void chroot(int x){access(x),splay(x),rev[x]^=1;}
void link(int x,int y){chroot(x),splay(x),fa[x]=y;}
void cut(int x,int y){chroot(x),access(y),splay(x),fa[y]=ls=rs=c[y][0]=c[y][1]=0,pushup(x),pushup(y);}
int qry(int x,int y){chroot(x),access(y),splay(x);return (fdrt(y)!=x)?0:e[x];}
void ins(int &x,int pre,int l,int r,int pos,int dt){
x=++cnt,L[x]=L[pre],R[x]=R[pre];
sum[x]=sum[pre]+dt; if(l==r) return;
if(pos<=mid)ins(L[x],L[pre],l,mid,pos,dt);
else ins(R[x],R[pre],mid+1,r,pos,dt);
}
int getans(int x,int l,int r,int minn){
if(r<minn||!sum[x]) return 0; if(l>=minn) return sum[x];
return getans(L[x],l,mid,minn)+getans(R[x],mid+1,r,minn);
}
int main(){
for(int T=read(),Q;T;T--,cnt=0){
n=read(),m=read(),Q=read(),tot=n,memset(c,0,sizeof(c));
memset(rt,0,sizeof(rt)),memset(fa,0,sizeof(fa)),memset(e,0x3f,sizeof(e));
for(int i=1;i<=m;i++){
int now; u[i]=read(),v[i]=read(),rt[i]=rt[i-1],tot++;
if(u[i]==v[i]) continue; now=qry(u[i],v[i]);
if(now) ins(rt[i],rt[i],1,m,now,-1),cut(u[now],v[now]);
ins(rt[i],rt[i],1,m,i,1),link(u[i],tot),link(v[i],tot);
}
while(Q--){
int tl=read(),tr=read(),num;
num=getans(rt[tr],1,m,tl);
write(n-num),putchar('\n');
}
}
return 0;
}
Code Chef - Chef and Graph Queries的更多相关文章
- [BZOJ 3514]Codechef MARCH14 GERALD07加强版 (CHEF AND GRAPH QUERIES)
[BZOJ3514] Codechef MARCH14 GERALD07加强版 (CHEF AND GRAPH QUERIES) 题意 \(N\) 个点 \(M\) 条边的无向图,\(K\) 次询问保 ...
- 【CodeChef】Chef and Graph Queries
Portal --> CC Chef and Graph Queries Solution 快乐数据结构题(然而好像有十分优秀的莫队+可撤销并查集搞法qwq) 首先考虑一种方式来方便一点地..计 ...
- [CodeChef - GERALD07 ] Chef and Graph Queries
Read problems statements in Mandarin Chineseand Russian. Problem Statement Chef has a undirected gra ...
- [bzoj3514][CodeChef GERALD07] Chef ans Graph Queries [LCT+主席树]
题面 bzoj上的强制在线版本 思路 首先可以确定,这类联通块相关的询问问题,都可以$LCT$+可持久化记录解决 用LCT维护生成树作为算法基础 具体而言,从前往后按照边的编号顺序扫一遍边 如果这条边 ...
- Chef and Graph Queries CodeChef - GERALD07
https://vjudge.net/problem/CodeChef-GERALD07 可以用莫队+带撤销并查集做 错误记录: 1.调试时数组开小了,忘了改大就交了 2.88行和91行少了备份num ...
- BZOJ3514 / Codechef GERALD07 Chef and Graph Queries LCT、主席树
传送门--BZOJ 传送门--VJ 考虑使用LCT维护时间最大生成树,那么对于第\(i\)条边,其加入时可能会删去一条边.记\(pre_i\)表示删去的边的编号,如果不存在则\(pre_i = 0\) ...
- CF&&CC百套计划2 CodeChef December Challenge 2017 Chef And Easy Xor Queries
https://www.codechef.com/DEC17/problems/CHEFEXQ 题意: 位置i的数改为k 询问区间[1,i]内有多少个前缀的异或和为k 分块 sum[i][j] 表示第 ...
- codechef Chef And Easy Xor Queries
做法:我们考虑前缀异或和,修改操作就变成了区间[i,n]都异或x 查询操作就变成了:区间[1,x]中有几个k 显然的分块,每个块打一个tag标记表示这个块中所有的元素都异或了tag[x] 然后处理出这 ...
- codechef AUG17 T2 Chef and Mover
Chef and Mover Problem Code: CHEFMOVR Chef's dog Snuffles has so many things to play with! This time ...
随机推荐
- ios 深入讲解iOS键盘一:控制键盘隐藏显示
在iOS的开发中,我们一般使用UITextField.UITextView处理文字输入等操作,大部分情况下我们只需要一两行代码去手动管理键盘的显示隐藏:让UITextField或UITextView成 ...
- HTTP 304 详解
把Last-Modified 和ETags请求的http报头一起使用,这样可利用客户端(例如浏览器)的缓存.因为服务器首先产生 Last-Modified/Etag标记,服务器可在稍后使用它来判断页面 ...
- R中常用数据挖掘算法包
数据挖掘主要分为4类,即预测.分类.聚类和关联,根据不同的挖掘目的选择相应的算法.下面对R语言中常用的数据挖掘包做一个汇总: 连续因变量的预测: stats包 lm函数,实现多元线性回归 stats包 ...
- Android AbsoluteLayout绝对布局
绝对布局也叫坐标布局,指定元素的绝对位置,因为适应性很差,一般很少用到.可以使用RelativeLayout替代. 常用属性: android:layout_x --------组件x坐标 andro ...
- 【leetcode刷题笔记】Remove Duplicates from Sorted List II
Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numb ...
- 第三篇、javascript整数和字符串
一.整数 JavaScript中不区分整数值和浮点数值,JavaScript中所有数字均用浮点数值表示. 转换: parseInt(..) 将某值转换成数字,不成功则NaN parseFloat ...
- 在ubuntu上为android系统编写Linux驱动程序【转】
本文转载自:http://blog.csdn.net/luoshengyang/article/details/6568411 在智能手机时代,每个品牌的手机都有自己的个性特点.正是依靠这种与众不同的 ...
- MySQL服务器调优思路
1.mysqladmin -uroot ext|awk '/Queries/{q=$4}/Threads_connected/{c=$4}/Threads_running/{r=$4}END{prin ...
- 《python基础教程(第二版)》学习笔记 文件和素材(第11章)
<python基础教程(第二版)>学习笔记 文件和素材(第11章) 打开文件:open(filename[,mode[,buffering]]) mode是读写文件的模式f=open(r' ...
- 推荐ajaxfilemanager for tiny_mce 比较完善的tiny_mce编辑器的图片上传及图片管理插件PHP版 支持中文
tiny_mce编辑器,我觉得挺简洁.好用的,但就是图片上传的插件是收费的,而且网上找了半天也没有找到开源好用的上传插件. 不过功夫不负有心人,终于还就被我找到一款相当满意的插件. 这个插件的名字叫a ...