GERALD07加强版题解
题目描述:
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加强版题解的更多相关文章
- 【LCT+主席树】BZOJ3514 Codechef MARCH14 GERALD07加强版
3514: Codechef MARCH14 GERALD07加强版 Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 2023 Solved: 778 ...
- [BZOJ 3514]Codechef MARCH14 GERALD07加强版 (CHEF AND GRAPH QUERIES)
[BZOJ3514] Codechef MARCH14 GERALD07加强版 (CHEF AND GRAPH QUERIES) 题意 \(N\) 个点 \(M\) 条边的无向图,\(K\) 次询问保 ...
- bzoj3514 Codechef MARCH14 GERALD07加强版 lct预处理+主席树
Codechef MARCH14 GERALD07加强版 Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 1951 Solved: 746[Submi ...
- 【BZOJ-3514】Codechef MARCH14 GERALD07加强版 LinkCutTree + 主席树
3514: Codechef MARCH14 GERALD07加强版 Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 1288 Solved: 490 ...
- BZOJ 3514: Codechef MARCH14 GERALD07加强版( LCT + 主席树 )
从左到右加边, 假如+的边e形成环, 那么记下这个环上最早加入的边_e, 当且仅当询问区间的左端点> _e加入的时间, e对答案有贡献(脑补一下). 然后一开始是N个连通块, 假如有x条边有贡献 ...
- BZOJ 3514: Codechef MARCH14 GERALD07加强版 [LCT 主席树 kruskal]
3514: Codechef MARCH14 GERALD07加强版 Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 1312 Solved: 501 ...
- BZOJ_3514_Codechef MARCH14 GERALD07加强版_主席树+LCT
BZOJ_3514_Codechef MARCH14 GERALD07加强版_主席树+LCT Description N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数. I ...
- [BZOJ3514]CodeChef MARCH14 GERALD07加强版(LCT+主席树)
3514: Codechef MARCH14 GERALD07加强版 Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 2177 Solved: 834 ...
- BZOJ3514 GERALD07加强版
GERALD07 Description N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数. Input 第一行四个整数N.M.K.type,代表点数.边数.询问数以及询问 ...
随机推荐
- java基础学习笔记二(接口、super、this)
一.super 和 this的用法 主要解释一下引用构造函数的用法 super(参数):调用父类中的某一个构造函数(应该为构造函数中的第一条语句) this(参数):调用本类中另一种形式的构造函数(应 ...
- bzoj 2015
http://www.lydsy.com/JudgeOnline/problem.php?id=2015 裸最短路(' ' ) 不过我最初以为是mst (' ' ) #include & ...
- css float 浮动
CSS Float(浮动) 什么是 CSS Float(浮动)?大理石平台价格 CSS 的 Float(浮动),会使元素向左或向右移动,其周围的元素也会重新排列. Float(浮动),往往是用于图像, ...
- UNP学习 Unix域协议
Unix域协议并不是一个实际的协议族,它只是在同一台主机上进行客户-服务器通信时,使用与在不同主机上的客户和服务器间通信时相同的API的一种方法. 当客户和服务器在同一台主机上时,Unix域协议是这套 ...
- SPI总线介绍和裸机编程分析
一.SPI总线结构 SPI(Serial Peripheral Interface)串行外设接口,是一种高速的,全双工,同步的通信总线.采用主从模式(Master Slave)架构,支持多个slave ...
- 【Flutter学习】之动画实现原理浅析(三)
一,概述 Flutter动画库的核心类是Animation对象,它生成指导动画的值,Animation对象指导动画的当前状态(例如,是开始.停止还是向前或者向后移动),但它不知道屏幕上显示的内容.动画 ...
- OC学习篇之---Foundation框架中的NSDirctionary类以及NSMutableDirctionary类
昨天学习了Foundation框架中NSArray类和NSMutableArray类:http://blog.csdn.net/jiangwei0910410003/article/details/4 ...
- 科学把妹法 ( ̄▽ ̄)"
曾经有一位生物学人士,公布了工科把妹第一弹,暨“巴甫洛夫把妹法”: 每天给你那位心仪的女同事/女同学的抽屉里都放上精心准备的早餐,并且保持缄默不语,无论她如何询问,都不要说话. 如此坚持一至两个月, ...
- 用 Flask 来写个轻博客 (6) — (M)VC_models 的关系(one to many)
Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 扩展阅读 前言 一对多 再一次 sync db How to use ...
- 数据库SQL调优的几种方式(转)
原文地址:https://blog.csdn.net/u010520146/article/details/81161762 在项目中,SQL的调优对项目的性能来讲至关重要,所有掌握常见的SQL调优方 ...