3514: Codechef MARCH14 GERALD07加强版

Time Limit: 60 Sec  Memory Limit: 256 MB
Submit: 1288  Solved: 490
[Submit][Status][Discuss]

Description

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

Input

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

Output

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

Sample Input

3 5 4 0
1 3
1 2
2 1
3 2
2 2
2 3
1 5
5 5
1 2

Sample Output

2
1
3
1

HINT

对于100%的数据,1≤N、M、K≤200,000。

2016.2.26提高时限至60s

Source

By zhonghaoxi

Solution

这应该算是动态图问题吧?? 问了一下ShallWe,用LCT维护动态图问题的一种离线做法是维护一颗 时间最大生成树 ,所以这个也是一样。

思路非常的巧妙,首先维护一颗 时间最大生成树 ,按时间顺序加边。

设当前加边为$<u,v>$,如果$u$和$v$属于同一个联通块,则加入$<u,v>$必然会形成环,那么切掉这个环上的边权(时间)最小的边,连上这个边,记这个被切掉的边为$pop_{i}$

然后这个题要求联通块的个数,然后发现,对于$pop$存在一个性质:

对于一条边$x$,在边$x$和使边$x$被切的边$y$之间连上的边,是不会与使边$x$被切得边$y$出现环的,即如果$r>y>l>x$则$y$必然会使联通块-1

所以问题就可以转化为求$[l,r]$中$pop<l$的$pop$的个数,这个可以用主席树去维护,所以答案就是$N-sum$。

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define INF 0x3fffffff
#define MAXN 400010
inline int read()
{
int x=0,f=1; char ch=getchar();
while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
int N,M,K,T,last;
struct EdgeNode{int u,v;}edge[MAXN];
namespace LCT
{
int fa[MAXN],son[MAXN][2],id[MAXN],tim[MAXN]; bool rev[MAXN];
inline void Init() {for (int i=1; i<=N; i++) id[i]=i,tim[i]=INF;}
inline bool is_root(int x) {return !fa[x] || son[fa[x]][0]!=x&&son[fa[x]][1]!=x;}
inline int Min(int x,int y) {return tim[x]<tim[y]? x:y;}
inline void Update(int x)
{
id[x]=x;
if (son[x][0]) id[x]=Min(id[x],id[son[x][0]]);
if (son[x][1]) id[x]=Min(id[x],id[son[x][1]]);
}
inline void Rev(int x) {if (!x) return; swap(son[x][0],son[x][1]),rev[x]^=1;}
inline void Pushdown(int x)
{
if (!x) return;
if (rev[x]) Rev(son[x][0]),Rev(son[x][1]),rev[x]^=1;
}
inline void Rotate(int x)
{
int y=fa[x],w=son[y][1]==x,z=fa[y];
son[y][w]=son[x][w^1];
if (son[x][w^1]) fa[son[x][w^1]]=y;
if (son[z][0]==y) son[z][0]=x; else if (son[z][1]==y) son[z][1]=x;
fa[x]=z; fa[y]=x; son[x][w^1]=y; Update(y);
}
int stack[MAXN];
inline void Splay(int x)
{
int t=x,top=0,y; stack[++top]=x;
while (!is_root(t)) stack[++top]=t=fa[t];
while (top) Pushdown(stack[top--]);
while (!is_root(x))
{
y=fa[x];
if (!is_root(y))
if ((son[fa[y]][0]==y)^(son[y][0]==x)) Rotate(x);
else Rotate(y);
Rotate(x);
}
Update(x);
}
inline void Access(int x) {for (int y=0; x; y=x,x=fa[x]) Splay(x),son[x][1]=y,Update(x);}
inline void Makeroot(int x) {Access(x); Splay(x); Rev(x);}
inline void Link(int x,int y) {Makeroot(x); fa[x]=y; Access(x);}
inline void Cut(int x) {Access(x); Splay(x); fa[son[x][0]]=0; son[x][0]=0; Update(x);}
inline void Cut(int x,int y) {Makeroot(x); Access(y); Cut(y);}
inline int Find(int x) {Access(x); Splay(x); while (son[x][0]) x=son[x][0]; return x;}
inline int Query(int x,int y) {Makeroot(x); Access(y); Splay(y); return id[y];}
}using namespace LCT; namespace PrTree
{
int root[MAXN],lson[MAXN*20],rson[MAXN*20],sum[MAXN*20],sz;
inline void Insert(int l,int r,int &now,int par,int val)
{
now=++sz; sum[now]=sum[par]+1;
if (l==r) {return;}
lson[now]=lson[par],rson[now]=rson[par];
int mid=(l+r)>>1;
if (val<=mid) Insert(l,mid,lson[now],lson[par],val);
else Insert(mid+1,r,rson[now],rson[par],val);
}
inline int Query(int l,int r,int L,int R,int val)
{
if (r<=val) return sum[R]-sum[L];
int mid=(l+r)>>1;
if (val<=mid) return Query(l,mid,lson[L],lson[R],val);
else return Query(l,mid,lson[L],lson[R],val)+Query(mid+1,r,rson[L],rson[R],val);
}
}using namespace PrTree;
int pop[MAXN];
int main()
{
N=read(),M=read(),K=read(),T=read();
for (int i=1; i<=M; i++) edge[i].u=read(),edge[i].v=read();
LCT::Init();
for (int i=1; i<=M; i++)
{
int u=edge[i].u,v=edge[i].v;
if (u==v) {pop[i]=i; continue;}
if (LCT::Find(u)==LCT::Find(v))
{
pop[i]=LCT::Query(u,v);
LCT::Cut(u,pop[i]); LCT::Cut(v,pop[i]);
pop[i]-=N;
}
id[i+N]=i+N,tim[i+N]=i;
LCT::Link(u,i+N); LCT::Link(v,i+N);
}
// for (int i=1; i<=M; i++) printf("%d ",pop[i]); puts("");
for (int i=1; i<=M; i++) PrTree::Insert(0,M,root[i],root[i-1],pop[i]);
while (K--)
{
int L=read(),R=read();
if (T) L^=last,R^=last;
printf("%d\n",last=N-Query(0,M,root[L-1],root[R],L-1));
}
return 0;
}

  

【BZOJ-3514】Codechef MARCH14 GERALD07加强版 LinkCutTree + 主席树的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

  7. BZOJ 3514: Codechef MARCH14 GERALD07加强版 (LCT维护最大生成树+主席树)

    题意 给出nnn个点,mmm条边.多次询问,求编号在[l,r][l,r][l,r]内的边形成的联通块的数量,强制在线. 分析 LCTLCTLCT维护动态最大生成树,先将每条边依次加进去,若形成环就断掉 ...

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

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

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

    题解: 还是比较简单的 首先我们的思路是 确定起点 然后之后贪心的选择边(也就是越靠前越希望选) 我们发现我们只需要将起点从后向前枚举 然后用lct维护连通性 因为强制在线,所以用主席树记录状态就可以 ...

随机推荐

  1. Easyui dialog中嵌入iframe

    如果easyui dialog的地址属性用href超链接,easyui 不会加载整个url页面,只会截取url目标页的body体间的html, 如果想加载把其他页面 加载进dialog的iframe中 ...

  2. xcode8 storyboard 控件显示错位

    升级xcode8 后选择device 为6s 出现上面的情况,控件显示异常.使用Update Frame 显示正常.不能选择Update Constraints   如果误选 commend + Z ...

  3. 阶段一:为View设置阴影和弹出动画(天气应用)

    “阶段一”是指我第一次系统地学习Android开发.这主要是对我的学习过程作个记录. 上一篇阶段一:通过网络请求,获得并解析JSON数据(天气应用)完成了应用的核心功能,接下来就要对它进行优化.今天我 ...

  4. Linux 6.5(oracle 11.2.0.4)单实例ASM安装

    Linux 6.5(oracle 11.2.0.4) 1.解析主机.配置网络等 /etc/hosts /etc/sysconfig/network /etc/init.d/NetworkManager ...

  5. 查看Oracle执行计划

    1.PL/SQL解释计划窗口 优点:方面 缺点:看到信息有限 2.explain_plan for 针对某个句子优化较方便 3.sqlplus Sqlplus里输入命令: set autotrace ...

  6. 使用Nexus搭建Maven本地仓库

    阅读目录 序 Nexus 本文版权归mephisto和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作. 文章是哥(mephisto)写的,SourceLink 序 在工作中可能存在有 ...

  7. Web系统性能测试术语简介

    并发用户 并发一般分为两种情况.一种是严格意义上的并发,即所有的用户在同一时刻做同一件事情或者操作.这种操作一般指做同一类型的业务,比如在信用卡审批业务中,一定数目的用户在同一时刻对已经完成的审批业务 ...

  8. 烂泥:python2.7和python3.5源码安装

    本文由ilanniweb提供友情赞助,首发于烂泥行天下 想要获得更多的文章,可以关注我的微信ilanniweb 前几天在centos6.6安装ansible时,一直提示python版本不对,导致不能安 ...

  9. 理解 neutron(15):Neutron linux-bridge-agent 创建 linux bridge 的简要过程

    学习 Neutron 系列文章: (1)Neutron 所实现的虚拟化网络 (2)Neutron OpenvSwitch + VLAN 虚拟网络 (3)Neutron OpenvSwitch + GR ...

  10. input输入框的光标

    上午的时候,以前一起配合Java后端的哥们问了个input光标的问题. 需求是这样:只能输入数字的input(一开始以为是输入金额这些的,后来才晓得是用来填写手机号) 他采用是直接百度来的如下方法: ...