题目描述:

  N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数。

输入格式:

  第一行四个整数N、M、K、type,代表点数、边数、询问数以及询问是否加密。 接下来M行,代表图中的每条边。 接下来K行,每行两个整数L、R代表一组询问。对于type=0的测试点,读入的L和R即为询问的L、R;对于type=1的测试点,每组询问的L、R应为L xor lastans和R xor lastans。

输出格式:

  K行每行一个整数代表该组询问的联通块个数。

题解:

  连通问题首先考虑LCT。

  考虑连通块个数的计算方法。

  连通块个数=点数-去掉重边后的边数。

  逐个枚举边,如果这条边连接的两个点没有连通,连接这条边;反之,把两点间最早的边弹出,连接这条边,并记录弹出边的编号。

  每次查询区间时,如果这条边弹出的边在区间内,那么这条边是无效的。

  所以问题转化为求区间内小于某个数的数的个数,可以主席树维护。

  时间复杂度$O(nlog_n)$

Code:

 #include<iostream>
#include<cstdio>
using namespace std;
const int N=;
const int inf=1e9+;
int n,m,k,ty,cnt,top;
int a[N<<],st[N<<],ch[N<<][],f[N<<],rev[N<<],mi[N<<];
int u[N],v[N],rt[N],b[N],an[N];
struct seg{
int lc,rc,w;
}t[N<<];
int read()
{
int s=;char c=getchar();
while(c<''||c>'') c=getchar();
while(c>=''&&c<=''){
s=(s<<)+(s<<)+c-'';
c=getchar();
}
return s;
}
int get(int x)
{
return ch[f[x]][]==x;
}
bool isroot(int x)
{
return ch[f[x]][]!=x&&ch[f[x]][]!=x;
}
void pushup(int x)
{
mi[x]=a[x];
if(ch[x][]) mi[x]=min(mi[x],mi[ch[x][]]);
if(ch[x][]) mi[x]=min(mi[x],mi[ch[x][]]);
}
void pushdown(int x)
{
if(rev[x]){
swap(ch[x][],ch[x][]);
if(ch[x][]) rev[ch[x][]]^=;
if(ch[x][]) rev[ch[x][]]^=;
rev[x]=;
}
}
void rotate(int x)
{
int y=f[x],z=f[y],k=get(x);
if(!isroot(y)){
if(ch[z][]==y) ch[z][]=x;
else ch[z][]=x;
}
f[x]=z;f[y]=x;f[ch[x][k^]]=y;
ch[y][k]=ch[x][k^];ch[x][k^]=y;
pushup(y);pushup(x);
}
void splay(int x)
{
top=;st[++top]=x;
for(int i=x;!isroot(i);i=f[i]) st[++top]=f[i];
for(int i=top;i>=;i--) pushdown(st[i]);
while(!isroot(x)){
int y=f[x];
if(!isroot(y)){
if(get(x)==get(y)) rotate(y);
else rotate(x);
}
rotate(x);
}
}
void access(int x)
{
for(int y=;x;y=x,x=f[x]){
splay(x);ch[x][]=y;pushup(x);
}
}
void makeroot(int x)
{
access(x);splay(x);
rev[x]^=;
}
void split(int x,int y)
{
makeroot(x);
access(y);splay(y);
}
void link(int x,int y)
{
makeroot(x);
f[x]=y;
}
void cut(int x,int y)
{
split(x,y);
f[x]=ch[y][]=;
}
int find(int x)
{
access(x);splay(x);
pushdown(x);
while(ch[x][]){
pushdown(ch[x][]);
x=ch[x][];
}
splay(x);
return x;
}
void insert(int lk,int &rk,int l,int r,int x)
{
if(rk==) rk=++cnt;
t[rk].w=t[lk].w+;
if(l==r) return;
int mid=(l+r)>>;
if(x<=mid){
t[rk].rc=t[lk].rc;
insert(t[lk].lc,t[rk].lc,l,mid,x);
}
else{
t[rk].lc=t[lk].lc;
insert(t[lk].rc,t[rk].rc,mid+,r,x);
}
}
int que(int lk,int rk,int L,int R,int l,int r)
{
if(L>=l&&R<=r) return t[rk].w-t[lk].w;
int mid=(L+R)>>;
if(r<=mid) return que(t[lk].lc,t[rk].lc,L,mid,l,r);
else if(l>mid) return que(t[lk].rc,t[rk].rc,mid+,R,l,r);
else return que(t[lk].lc,t[rk].lc,L,mid,l,r)+que(t[lk].rc,t[rk].rc,mid+,R,l,r);
}
int main()
{
n=read();m=read();k=read();ty=read();
for(int i=;i<=n;i++) a[i]=inf;
for(int i=;i<=m;i++){
u[i]=read();v[i]=read();a[i+n]=i;
if(u[i]!=v[i]){
int x=find(u[i]),y=find(v[i]);
if(x==y){
split(u[i],v[i]);
b[i]=mi[v[i]];
cut(u[b[i]],b[i]+n);
cut(b[i]+n,v[b[i]]);
}
link(u[i],i+n);
link(i+n,v[i]);
insert(rt[i-],rt[i],,m,b[i]);
}
else rt[i]=rt[i-];
}
for(int i=;i<=k;i++){
int l=read(),r=read();
if(ty){
l^=an[i-];r^=an[i-];
}
an[i]=n-que(rt[l-],rt[r],,m,,l-);
}
for(int i=;i<=k;i++) printf("%d\n",an[i]);
return ;
}

GERALD07加强版题解的更多相关文章

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

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

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

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

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

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

  4. 【BZOJ-3514】Codechef MARCH14 GERALD07加强版 LinkCutTree + 主席树

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

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

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

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

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

  7. BZOJ_3514_Codechef MARCH14 GERALD07加强版_主席树+LCT

    BZOJ_3514_Codechef MARCH14 GERALD07加强版_主席树+LCT Description N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数. I ...

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

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

  9. BZOJ3514 GERALD07加强版

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

随机推荐

  1. c# 定义operator运算符

    public void TestFunc() { Complex complex1 = new Complex(); Complex complex2 = new Complex(); var s = ...

  2. boost string algorithm

    The Boost.StringAlgorithms library provides many free-standing functions for string manipulation. 1. ...

  3. string,const char*, char*转换之后还是指向同一片内存地址么?

    class Same { public: void reverse(const char* str) { char* A = const_cast<char*>(str); A[] = ' ...

  4. MSSQLSERVER错误1

      错误信息 数据库日志记录 09/07/2017 16:10:31,登录,未知,Login failed for user 'NT AUTHORITY\SYSTEM'. 原因: 无法打开明确指定的数 ...

  5. Sqli labs系列-less-5&6 报错注入法(下)

    我先输入 ' 让其出错. 然后知道语句是单引号闭合. 然后直接 and 1=1 测试. 返回正常,再 and 1=2 . 返回错误,开始猜表段数. 恩,3位.让其报错,然后注入... 擦,不错出,再加 ...

  6. 前端每日实战:81# 视频演示如何用纯 CSS 创作一个变色旋转动画

    效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/ejZWKL 可交互视频 此视频是可 ...

  7. 把我坑惨的一个MySQL双引号!

    来源:For DBA www.fordba.com/mysql-double-quotation-marks-accident.html 一.前言 最近经常碰到开发误删除误更新数据,这不,他们又给我找 ...

  8. Msys2升级后不能编译

    Msys2升级后不能编译 */--> code {color: #FF0000} pre.src {background-color: #002b36; color: #839496;} cod ...

  9. python while循坏和for循坏

    while循坏 while 条件: 条件成立,执行循坏体(注意,while循坏必须有结束条件,不然会进入死循坏) 简单做个演示: # -*- coding:utf-8 -*- # Author:覃振鸿 ...

  10. HTTP、HTTP1.0、HTTP1.1、HTTP2.0、HTTPS

      一.HTTP HTTP(超文本传输协议,HyperText Transfer Protocol)是应用层的协议,目前在互联网中应用广泛. 它被设计用于Web浏览器和Web服务器之间的通信,但它也可 ...