来自蒟蒻 \(Hero \_of \_Someone\) 的 \(LCT\) 学习笔记
$
$
又是一道骚题......
先讲一个结论:
假设我们用 \(LCT\) 来做这道题, 在插入边 \(i\) 的时候如果遇到了环, 则将环上最早加入的那条边删掉, 并插入边 \(i\),
记 \(cnm [i]\) 为被删除边的编号, 如果插入边 \(i\) 时没有遇到环, 则记 \(cnm[i]=0\).
那么, 每一个询问的答案即为, \(n\ -\ [l,r]中小于\ l\ 的\ cnm[i]\ 的个数\).
$
$
证明:
假设加入边 \(i\) 后形成的的环上没有 \(i\) 和 \(cnm[i]\) 这两条边, 那么这个环将变成两个连通块,
而在加入 \(i\) 且 \(cnm[i]<l\) (即在该询问中, \(cnm[i]\) 并不存在于图中)时, 这两个连通块变成了一个连通块, 即连通块数量 \(-1\) ,
所以 \([l,r]\) 中小于 \(l\) 的 \(cnm[i]\) 的个数即为减少的连通块数量, 得证.
$
$
所以这道题的做法就出来了, 用 \(LCT\) 来求 \(cnm[]\) , 主席树或者树套树维护 \([l,r]\) 中小于 \(l\) 的 \(cnm[i]\) 的个数
$
$

//made by Hero_of_Someone
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define N (400010)
#define RG register
using namespace std;
inline int gi(){ RG int x=0,q=1; RG char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
  if(ch=='-') q=-1,ch=getchar(); while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=getchar(); return q*x; }
void File(){freopen(".in","r",stdin);freopen(".out","w",stdout);}

int n,m,k,type,cnm[N];
struct Edge{int u,v;}E[N],e[N];
//------------ lct -----------------------------
int ch[N][2],fa[N],rev[N];
int val[N],Min[N];

inline void cur(int x,int y){ val[x]=Min[x]=y; }

inline void up(int x){
  Min[x]=min(Min[ch[x][0]],Min[ch[x][1]]);
  Min[x]=min(Min[x],val[x]);
}

inline void reverse(int x){
  if(!x) return ;
  swap(ch[x][0],ch[x][1]);
  rev[x]^=1;
}

inline void down(int x){
  if(!rev[x]) return ;
  reverse(ch[x][0]);
  reverse(ch[x][1]);
  rev[x]=0;
}

inline bool is_root(int x){ return ch[fa[x]][0]!=x && x!=ch[fa[x]][1]; }

inline bool lr(int x){ return x==ch[fa[x]][1]; }

inline void rotate(int x){
  RG int y=fa[x],z=fa[y],k=lr(x);
  if(!is_root(y)) ch[z][lr(y)]=x;
  fa[x]=z; fa[ch[x][k^1]]=y; fa[y]=x;
  ch[y][k]=ch[x][k^1]; ch[x][k^1]=y;
  up(y); up(x);
}

int st[N];
inline void splay(int x){
  RG int y=x,top=0;
  while(1){
    st[++top]=y;
    if(is_root(y)) break;
    y=fa[y];
  }
  for(RG int i=top;i;i--) down(st[i]);
  while(!is_root(x)){
    if(!is_root(fa[x])) rotate(lr(x)^lr(fa[x])?x:fa[x]);
    rotate(x);
  }
}

inline void access(int x){
  RG int y=0;
  while(x){ splay(x);
    ch[x][1]=y; fa[y]=x;
    up(x); y=x; x=fa[x];
  }
}

inline void make_root(int x){
  access(x); splay(x); reverse(x);
}

inline int query(int x,int y){
  make_root(x); access(y); splay(y);
  return Min[y];
}

inline int find(int x){
  while(fa[x]) x=fa[x];
  return x;
}

inline void link(int x,int y){
  if(find(x)==find(y)) return ;
  make_root(x); fa[x]=y;
}

inline void cut(int x,int y){
  make_root(x); access(y); splay(y);
  if(ch[y][0]==x) y=0,fa[x]=0,up(y);
}

inline void Insert(int id){
  RG int x=e[id].u,y=e[id].v;
  if(x==y){ cnm[id]=m+1; return ; }
  if(find(x)==find(y)){
    RG int tmp=query(x,y);
    cnm[id]=tmp;
    cut(e[tmp].u,n+tmp);
    cut(e[tmp].v,n+tmp);
  }
  cur(n+id,id);
  link(x,n+id);
  link(y,n+id);
}

inline void init(){
  n=gi(),m=gi(),k=gi(),type=gi();
  for(RG int i=0;i<=n;i++) cur(i,m+1);
  for(RG int i=1;i<=m;i++){
    e[i].u=gi(),e[i].v=gi();
    Insert(i);
  }
}

//------------ 主席树 --------------------------

int ans,cnt,A[N];
int sz,rt[N],sum[N*20];
int ls[N*20],rs[N*20];
inline void build(int& x,int y,int l,int r,int v){
  x=++sz;
  if(l==r){ sum[x]=sum[y]+1; return ; }
  RG int mid=(l+r)>>1;
  if(v<=A[mid]){ rs[x]=rs[y];
    build(ls[x],ls[y],l,mid,v);
  }
  else{ ls[x]=ls[y];
    build(rs[x],rs[y],mid+1,r,v);
  }
  sum[x]=sum[ls[x]]+sum[rs[x]];
}

inline int query(int x,int y,int l,int r,int v){
  if(l==r){ return A[l]<=v?sum[x]-sum[y]:0; }
  RG int mid=(l+r)>>1,ret=sum[ls[x]]-sum[ls[y]];
  if(v<=A[mid]) return query(ls[x],ls[y],l,mid,v);
  else return query(rs[x],rs[y],mid+1,r,v)+ret;
}

//----------------------------------------------

inline void work(){
  for(RG int i=1;i<=m;i++) A[i]=cnm[i];
  sort(A+1,A+m+1); A[0]=-1;
  for(RG int i=1;i<=m;i++)
    if(A[i]!=A[cnt]) A[++cnt]=A[i];
  if(A[cnt]<m+1) A[++cnt]=m+1;
  for(RG int i=1;i<=m;i++)
    build(rt[i],rt[i-1],1,cnt,cnm[i]);
  while(k--){
    RG int l=gi(),r=gi();
    if(type) l^=ans,r^=ans;
    ans=n-query(rt[r],rt[l-1],1,cnt,l-1);
    printf("%d\n",ans);
  }
}

int main(){ init(); work(); return 0; }

沉迷Link-Cut tree无法自拔之:[BZOJ3514] Codechef MARCH14 GERALD07 加强版的更多相关文章

  1. 【LCT+主席树】BZOJ3514 Codechef MARCH14 GERALD07加强版

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

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

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

  3. bzoj3514 Codechef MARCH14 GERALD07加强版 lct预处理+主席树

    Codechef MARCH14 GERALD07加强版 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 1951  Solved: 746[Submi ...

  4. BZOJ3514 : Codechef MARCH14 GERALD07加强版

    以边编号为权值 用Link-cut Tree维护最大生成树 对于新加的第i条边(u,v) a[i]表示当a[i]这条边加入后连通块个数会减少 若u==v则a[i]=m 若u与v不连通则连上,a[i]= ...

  5. BZOJ3514 Codechef MARCH14 GERALD07加强版 LCT

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ3514 题意概括 N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数. N ...

  6. BZOJ3514: Codechef MARCH14 GERALD07加强版【LCT】【主席树】【思维】

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

  7. BZOJ3514: Codechef MARCH14 GERALD07加强版(LCT,主席树)

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

  8. BZOJ3514 Codechef MARCH14 GERALD07加强版 LCT+可持久化线段树

    自己独自想出来并切掉还是很开心的~ Code: #include <bits/stdc++.h> #define N 400005 #define inf 1000000000 #defi ...

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

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

随机推荐

  1. Iterable接口

    Iterable接口 总览 这个接口用来表明可以进行迭代.具体的迭代方式,可以通过iterator()方法获取到一个迭代器,在迭代器中会实现如何获取下一个元素,以及是否迭代结束. java8中源码如下 ...

  2. loj6062 pair

    直接套用霍尔定理. 由于A有多个选择,考虑维护B是否合法. 首先B数组的顺序显然是没有用的,可以直接排序. 然后每个A就都变成了向一个后缀连边. 对于B,原本需要check每一个集合是否满足|u|&l ...

  3. 微服务之Sping Cloud

    版本说明 Finchley SR2 价值简要 微服务之间是松耦合,跨不同业务部门,提供非常充分的灵活性,加快项目开发完成效率,方便组件化独立可扩展性及复用. 微服务应用结构表现 组件简要 1. Eur ...

  4. [原]Veracrypt使用Yubikey作为安全令牌

    今天刚刚到货Yubikey 5 美亚 直邮 ,易客满国际,国内居然是顺丰配送,点个赞. 必备的控件 https://developers.yubico.com/yubikey-manager-qt/R ...

  5. 在Ubuntu18.04下将应用程序添加到启动器

    # 在启动器里面给应用程序添加一个快捷方式 在linux(ubuntu)平台下,很多小伙伴发现,自己去官网下载解压的软件不能自动添加到启动器,每次启动的时候需要再次进入软件目录输入命令,非常不方便.本 ...

  6. 20135337——linux实践三:ELF文件格式分析(32位系统)

    ELF文件格式分析 可重定位文件 十六进制形式显示内容 显示各个段.符号表相关信息 查看各个段信息 elf文件头信息 段表 符号表信息 查看堆栈 具体分析 1.ELF文件头信息(小字节优先,均十六进制 ...

  7. hash函数补分博客

    题目要求: 利用除留余数法为下列关键字集合的存储设计hash函数,并画出分别用开放寻址法和拉链法解决冲突得到的空间存储状态(散列因子取0.75) 关键字集合:85,75,57,60,65,(你的8位学 ...

  8. Selenium的自我总结1

    搞了一段时间的Selenium Web的自动化,针对项目要搭建了一套适合项目的测试框架(Selenium[POM/DataDriver]+TestNG+Ant+Jenkins).在最开始看Seleni ...

  9. Windows 通过命令行设置固定ip地址

    Winserver1709 之后 windows系统取消了GUI界面 设置ip地址 需要使用命令行界面进行 这里简单记录一下 打开win1709的虚拟机 进入命令行控制台 输入 ipconfig 查看 ...

  10. docker 构建dockerfile

    版本为: 使用cenotos 7 docker  版本 [root@zhao ~]# docker --versionDocker version 17.03.1-ce, build c6d412e ...