Read problems statements in Mandarin Chineseand Russian.

Problem Statement

Chef has a undirected graph G. This graph consists of N vertices and M edges. Each vertex of the graph has an unique index from 1 to N, also each edge of the graph has an unique index from 1 to M.

Also Chef has Q pairs of integers: LiRi (1 ≤ Li ≤ Ri ≤ M). For each pair LiRi, Chef wants to know: how many connected components will contain graph G if Chef erase all the edges from the graph, except the edges with indies X, where Li ≤ X ≤ Ri. Please, help Chef with these queries.

Input

The first line of the input contains an integer T denoting the number of test cases. The description of T test cases follows.
The first line of each test case contains three integers NMQ. Each of the next M lines contains a pair of integers ViUi - the current edge of graph G. Each of the next Q lines contains a pair of integers LiRi - the current query.

Output

For each query of each test case print the required number of connected components.

Constraints

  • 1 ≤ T ≤ 1000.
  • 1 ≤ NMQ ≤ 200000.
  • 1 ≤ UiVi ≤ N.
  • 1 ≤ Li ≤ Ri ≤ M.
  • Sum of all values of N for test cases is not greater than 200000. Sum of all values of M for test cases is not greater than 200000. Sum of all values of Q for test cases is not greater than 200000.
  • Graph G can contain self-loops and multiple edges.

Example

Input:
2
3 5 4
1 3
1 2
2 1
3 2
2 2
2 3
1 5
5 5
1 2
1 1 1
1 1
1 1
Output:
2
1
3
1
1

破题坑了一晚上

题目大意?见上面超链接的中文题面。

树 LCT 动态维护生成树

将所有询问按右端点递增顺序排序,从1到m依次加边。

用LCT维护当前的生成树,生成树中保留的是编号尽量大的边。

同时用线段树维护生成树中保留了哪些边(权值线段树,存编号)。

查询时,在线段树上查询$[L,R]$范围内有多少条边,若查询结果为$ x $,则连通块数为$n-x$

注意有自环和重边,这使得维护生成树的时候不能一律删编号最靠前的边,而要先查询生成树中有没有重边。

细节蛮多的。

注意多组数据,初始化结点的时候要初始化到n+m

 #include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
using namespace std;
const int INF=0x3f3f3f3f;
const int mxn=;
int read(){
int x=,f=;char ch=getchar();
while(ch<'' || ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>='' && ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
struct edge{
int x,y;
}e[mxn];
struct query{
int L,R;
int id;
bool operator < (const query &b)const{
return R<b.R;
}
}q[mxn];
int ans[mxn];
//
struct SGT{
int smm[mxn<<];
#define ls rt<<1
#define rs rt<<1|1
void clear(int ed){
ed=ed<<;
for(register int i=;i<=ed;i++)smm[i]=;
}
void pushup(int rt){smm[rt]=smm[ls]+smm[rs];return;}
void update(int p,int v,int l,int r,int rt){
if(l==r){
smm[rt]+=v;
return;
}
int mid=(l+r)>>;
if(p<=mid)update(p,v,l,mid,ls);
else update(p,v,mid+,r,rs);
pushup(rt);
return;
}
int query(int L,int R,int l,int r,int rt){
if(L<=l && r<=R){
return smm[rt];
}
int mid=(l+r)>>;
if(R<=mid)return query(L,R,l,mid,ls);
if(L>mid)return query(L,R,mid+,r,rs);
return query(L,R,l,mid,ls)+query(L,R,mid+,r,rs);
}
#undef ls
#undef rs
}SG;
int n,m,Q;
//
struct node{
int ch[],fa;
int val,mn,minpos;
bool rev;
}t[mxn];
int cnt=;
void rever(int x){
int &lc=t[x].ch[],&rc=t[x].ch[];
swap(lc,rc);
t[lc].rev^=;t[rc].rev^=;
return;
}
void PD(int x){
if(t[x].rev){
rever(x);
t[x].rev=;
}
return;
}
void pushup(int x){
int lc=t[x].ch[],rc=t[x].ch[];
t[x].mn=t[x].val;t[x].minpos=x;
if(t[lc].mn<t[x].mn){
t[x].mn=t[lc].mn; t[x].minpos=t[lc].minpos;
}
if(t[rc].mn<t[x].mn){
t[x].mn=t[rc].mn; t[x].minpos=t[rc].minpos;
}
return;
}
inline bool isroot(int x){
return (t[t[x].fa].ch[]^x)&&(t[t[x].fa].ch[]^x);
}
void rotate(int x){
int y=t[x].fa,z=t[y].fa,lc,rc;
if(t[y].ch[]==x)lc=;else lc=;rc=lc^;
if(!isroot(y)){
t[z].ch[t[z].ch[]==y]=x;
}
t[x].fa=z;t[y].fa=x;
t[t[x].ch[rc]].fa=y;
t[y].ch[lc]=t[x].ch[rc];
t[x].ch[rc]=y;
pushup(y);
return;
}
int st[mxn],top=;
void Splay(int x){
st[top=]=x;
for(int i=x;t[i].fa;i=t[i].fa){
st[++top]=t[i].fa;
}
while(top)PD(st[top--]);
while(!isroot(x)){
int y=t[x].fa,z=t[y].fa;
if(!isroot(y)){
if((t[y].ch[]==x)^(t[z].ch[]==y))rotate(x);
else rotate(y);
}
rotate(x);
}
pushup(x);
return;
}
//
void access(int x){
for(int y=;x;x=t[x].fa){
Splay(x);
t[x].ch[]=y;
pushup(x);
y=x;
}
return;
}
int find(int x){
access(x);Splay(x);
while(t[x].ch[]){
x=t[x].ch[];
}
return x;
}
void mkroot(int x){
access(x);Splay(x);
t[x].rev^=;
return;
}
void link(int x,int y){
mkroot(x); t[x].fa=y;
return;
}
void cut(int x,int y){
mkroot(x);
access(y);Splay(y);
if(t[y].ch[]==x){t[x].fa=;t[y].ch[]=;}
pushup(y);
return;
}
//
void solve(){
int hd=;
cnt=n;
for(int i=;i<=m;i++){//按序加边
int x=e[i].x,y=e[i].y;
if(x!=y && find(x)==find(y)){
bool flag=;
mkroot(x);access(y);Splay(y);
//
/* printf("-----\n");
for(int j=1;j<=cnt;j++){
printf("#%d: lc:%d rc:%d fa:%d\n",j,t[j].ch[0],t[j].ch[1],t[j].fa);
}
printf("-----\n");*/
//
int res=t[y].ch[];
while(t[res].ch[])res=t[res].ch[];
res=res-n;
if(res> && e[res].x==x && e[res].y==y){
flag=;
cut(x,res+n);
cut(y,res+n);
SG.update(res,-,,m,);
}
//
if(!flag){
mkroot(x);access(y);Splay(y);
int tar=t[y].minpos;
cut(e[tar-n].x,tar);
cut(e[tar-n].y,tar);
SG.update(tar-n,-,,m,);
}
}
++cnt;
if(x!=y){
t[cnt].val=t[cnt].mn=i;
t[cnt].minpos=cnt;
link(x,cnt);
link(cnt,y);
SG.update(i,,,m,);
}
while(hd<=Q && q[hd].R<=i){
if(q[hd].R==i){
ans[q[hd].id]=n-SG.query(q[hd].L,q[hd].R,,m,);
}
hd++;
}
}
return;
}
void init(int n,int m){
int ed=n+m;
t[].minpos=;t[].mn=INF;
for(register int x=;x<=ed;x++){
t[x].ch[]=t[x].ch[]=t[x].fa=;
t[x].minpos=;t[x].mn=INF;
t[x].val=INF;
t[x].rev=;
}
SG.clear(ed);
return;
}
int main(){
// freopen("in.txt","r",stdin);
int i;
int T=read();
while(T--){
n=read();m=read();Q=read();
init(n,m);
for(i=;i<=m;i++){
e[i].x=read();e[i].y=read();
if(e[i].x>e[i].y)swap(e[i].x,e[i].y);
}
for(i=;i<=Q;i++){
q[i].L=read();q[i].R=read();
q[i].id=i;
}
sort(q+,q+Q+);
solve();
for(i=;i<=Q;i++){
printf("%d\n",ans[i]);
}
}
return ;
}

[CodeChef - GERALD07 ] Chef and Graph Queries的更多相关文章

  1. [bzoj3514][CodeChef GERALD07] Chef ans Graph Queries [LCT+主席树]

    题面 bzoj上的强制在线版本 思路 首先可以确定,这类联通块相关的询问问题,都可以$LCT$+可持久化记录解决 用LCT维护生成树作为算法基础 具体而言,从前往后按照边的编号顺序扫一遍边 如果这条边 ...

  2. BZOJ3514 / Codechef GERALD07 Chef and Graph Queries LCT、主席树

    传送门--BZOJ 传送门--VJ 考虑使用LCT维护时间最大生成树,那么对于第\(i\)条边,其加入时可能会删去一条边.记\(pre_i\)表示删去的边的编号,如果不存在则\(pre_i = 0\) ...

  3. 【CodeChef】Chef and Graph Queries

    Portal --> CC Chef and Graph Queries Solution 快乐数据结构题(然而好像有十分优秀的莫队+可撤销并查集搞法qwq) 首先考虑一种方式来方便一点地..计 ...

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

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

  5. Chef and Graph Queries CodeChef - GERALD07

    https://vjudge.net/problem/CodeChef-GERALD07 可以用莫队+带撤销并查集做 错误记录: 1.调试时数组开小了,忘了改大就交了 2.88行和91行少了备份num ...

  6. Code Chef - Chef and Graph Queries

    传送门 题目大意 给定一个$n$个点$m$条边的无向图$(n,m\leq 200000)$. 有$q$每次询问$(q\leq 200000)$,每次给定一个区间$L,R$,求仅保留编号$\in[L,R ...

  7. [Codechef CHSTR] Chef and String - 后缀数组

    [Codechef CHSTR] Chef and String Description 每次询问 \(S\) 的子串中,选出 \(k\) 个相同子串的方案有多少种. Solution 本题要求不是很 ...

  8. Codechef FNCS Chef and Churu

    Disciption Chef has recently learnt Function and Addition. He is too exited to teach this to his fri ...

  9. 【Codechef】Chef and Bike(二维多项式插值)

    something wrong with my new blog! I can't type matrixs so I come back. qwq 题目:https://www.codechef.c ...

随机推荐

  1. spring 国际化i18n配置

    i18n(其来源是英文单词 internationalization的首末字符i和n,18为中间的字符数)是“国际化”的简称.在资讯领域,国际化(i18n)指让产品(出版物,软件,硬件等)无需做大的改 ...

  2. android入门 — ListView

    ListView主要是用来解决大量数据展示的问题,它的用途很广泛,几乎所有的app都会用到,比如说知乎.今日头条.微博.通讯录等. ListView允许用户通过上下滑动的方式将屏幕外的数据滚动到屏幕中 ...

  3. Spring Boot(四)@EnableXXX注解分析

    在学习使用springboot过程中,我们经常碰到以@Enable开头的注解,其实早在Spring3中就已经出现了类似注解,比如@EnableTransactionManagement.@ Enabl ...

  4. 高性能python

    参考来源:Python金融大数据分析第八章 提高性能有如下方法 1.Cython,用于合并python和c语言静态编译泛型 2.IPython.parallel,用于在本地或者集群上并行执行代码 3. ...

  5. mysql 重置 root 密码

    mysqld_safe --skip-grant-tables & UPDATE mysql.user SET authentication_string=PASSWORD('mima') W ...

  6. Prepare方法和UnPrepare方法

    Query组件提供的Prepare方法的作用是通知BDE或数据库服务器优化并准备执行SQL操作.Query的Prepare方法能优化执行的原因在于该方法是是在SQL语句执行前就对其进行分析.检查和编译 ...

  7. Ip合并

    import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.Fi ...

  8. BZOJ 2241 打地鼠(特技暴力)

    果然暴力出奇迹.. O(n^2m^2)=1e8 536ms能过. 枚举锤子的长和宽,再验证是否可以满足条件并更新答案. 我们先从左上角为(1,1)的先锤,显然锤的次数是a[1][1]. 锤(i,j)的 ...

  9. CenOS shell脚本

    1.先查看脚本解释器 [es@bigdata-senior01 ~]$ echo $SHELL /bin/bash 2.编写最简单的脚本 vi test.sh#第一行的脚本声明(#!)用来告诉系统使用 ...

  10. [luogu3806]【模板】点分治1

    description 求树上长度为\(k\)的路径是否存在. data range \[n\le 10000,k\le 10000000\] solution 点分治复习... 使用普通的点分治枚举 ...