bzoj 1018 线段树维护连通性
本题将一道LCT的题特殊化(支持加边和删边,询问图的连通性),将图变成了2×m的网格图,然后就神奇地可以用线段树来维护。
对于每个区间[l,r],维护其四个角落之间的连通性(仅仅通过[l,r]这段的边构建起的连通性)。
查询[l,r]时,先计算出[1,l-1],[l,r],[r+1,c]这三个线段的连通性,然后将[l,r]的四个角变成并查集的4个点,先用[l,r]中的6种关系更新,在看是否可以从左上角的点通过左边区间绕道左下角,以及从右上角通过右边区间绕道右下角,该并的并起来后直接看查询的点是否在一个集合即可。
/**************************************************************
Problem: 1018
User: idy002
Language: C++
Result: Accepted
Time:1472 ms
Memory:2840 kb
****************************************************************/ #include <cstdio>
#include <iostream>
#define maxn 100010
#define AB 1
#define AC 2
#define AD 4
#define BC 8
#define BD 16
#define CD 32
using namespace std; // a b
// c d typedef unsigned Stat; Stat stat[maxn];
int son[maxn][], ntot, root; int c;
bool er[][maxn], ed[maxn]; Stat merge( Stat l, Stat r, int mid ) {
Stat ab = ((l&AB)&&(r&AB)&&er[][mid]) || ((l&AD)&&(r&BC)&&er[][mid]) ? AB : ;
Stat cd = ((l&CD)&&(r&CD)&&er[][mid]) || ((l&BC)&&(r&AD)&&er[][mid]) ? CD : ;
Stat ad = ((l&AB)&&(r&AD)&&er[][mid]) || ((l&AD)&&(r&CD)&&er[][mid]) ? AD : ;
Stat bc = ((l&CD)&&(r&BC)&&er[][mid]) || ((l&BC)&&(r&AB)&&er[][mid]) ? BC : ;
Stat ac = (l&AC) || ((l&AB)&&(l&CD)&&(er[][mid])&&(er[][mid])&&(r&AC)) ? AC : ;
Stat bd = (r&BD) || ((r&AB)&&(r&CD)&&(er[][mid])&&(er[][mid])&&(l&BD)) ? BD : ;
return ab | ac | ad | bc | bd | cd;
}
void update( int nd, int lf, int rg ) {
stat[nd] = merge( stat[son[nd][]], stat[son[nd][]], (lf+rg)>> );
}
int build( int lf, int rg ) {
if( lf>rg ) return ;
int nd = ++ntot;
if( lf==rg ) {
stat[nd] = AB | CD;
return nd;
}
int mid = (lf+rg)>>;
son[nd][] = build( lf, mid );
son[nd][] = build( mid+, rg );
update( nd, lf, rg );
return nd;
}
void modify( int x, int nd, int lf, int rg ) {
if( lf==rg ) {
stat[nd] = AB | CD;
if( ed[lf] )
stat[nd] |= AC | BD | AD | BC;
return;
}
int mid = (lf+rg)>>;
if( x<=mid ) modify(x,son[nd][],lf,mid);
else modify(x,son[nd][],mid+,rg);
update(nd,lf,rg);
}
Stat query( int L, int R, int nd, int lf, int rg ) {
if( L<=lf&&rg<=R ) return stat[nd];
int mid = (lf+rg)>>;
if( R<=mid ) return query( L, R, son[nd][], lf, mid );
if( L>mid ) return query( L, R, son[nd][], mid+, rg );
Stat lstat = query( L, R, son[nd][], lf, mid );
Stat rstat = query( L, R, son[nd][], mid+, rg );
return merge(lstat,rstat,mid);
} int fa[];
void init() {
for( int i=; i<=; i++ ) fa[i]=i;
}
int find( int i ) {
return fa[i]==i ? i : fa[i]=find(fa[i]);
}
void unon( int a, int b ) {
a = find(a);
b = find(b);
fa[a] = b;
}
int main() {
scanf( "%d", &c );
root = build( , c );
while() {
char ch[]; scanf( "%s", ch );
if( ch[]=='E' ) return ;
int ax, ay, bx, by;
scanf( "%d%d%d%d", &ax, &ay, &bx, &by ); if( ch[]=='A' ) {
if( ay>by ) {
swap( ax, bx );
swap( ay, by );
}
Stat sl=, sc=, sr=;
if( ay> ) sl = query(,ay-,root,,c);
sc = query(ay,by,root,,c);
if( by<c ) sr = query(by+,c,root,,c); init();
if( sc&AB ) unon( , );
if( sc&AC ) unon( , );
if( sc&AD ) unon( , );
if( sc&BC ) unon( , );
if( sc&BD ) unon( , );
if( sc&CD ) unon( , );
if( (sl&BD) && er[][ay-] && er[][ay-] ) unon( , );
if( (sr&AC) && er[][by] && er[][by] ) unon( , ); bool ok = false;
if( ax== && bx== ) {
ok = find( ) == find( );
} else if( ax== && bx== ) {
ok = find( ) == find( );
} else if( ax== && bx== ) {
ok = find( ) == find( );
} else if( ax== && bx== ) {
ok = find( ) == find( );
} printf( "%s\n", ok ? "Y" : "N" );
} else {
bool *p;
if( ax==bx ) {
p = &er[ax][min(ay,by)];
} else {
p = &ed[ay];
}
*p = ch[]=='O';
modify( ay, root, , c );
if( ay!=by )
modify( by, root, , c );
}
}
}
bzoj 1018 线段树维护连通性的更多相关文章
- BZOJ 1018 线段树维护图的连通性问题
思路: 我们可以搞一棵线段树 对于一段区间有6种情况需要讨论 左上右下.左上右上.左下右下.左下右上 这四种比较好维护 用左上右下举个例子吧 就是左儿子的左上右下&左区间到右区间下面有路&am ...
- BZOJ 1018 线段树维护图连通性
用8个bool维护即可分别为LURU,LURD,LDRU,LDRD,LULD,RURD,Side[1],Side[2]即可. Side表示这一块有没有接到右边.Merge一下就可以了.码农题,WA了一 ...
- [BZOJ 3995] [SDOI2015] 道路修建 【线段树维护连通性】
题目链接:BZOJ - 3995 题目分析 这道题..是我悲伤的回忆.. 线段树维护连通性,与 BZOJ-1018 类似,然而我省选之前并没有做过 1018,即使它在 ProblemSet 的第一页 ...
- BZOJ.1018.[SHOI2008]堵塞的交通(线段树维护连通性)
题目链接 只有两行,可能的路径数不多,考虑用线段树维护各种路径的连通性. 每个节点记录luru(left_up->right_up),lurd,ldru,ldrd,luld,rurd,表示这个区 ...
- [BZOJ1018][SHOI2008]堵塞的交通traffic 线段树维护连通性
1018: [SHOI2008]堵塞的交通traffic Time Limit: 3 Sec Memory Limit: 162 MB Submit: 3795 Solved: 1253 [Sub ...
- BZOJ 2124 线段树维护hash值
思路: http://blog.csdn.net/wzq_QwQ/article/details/47152909 (代码也是抄的他的) 自己写得垃圾线段树怎么都过不了 隔了两个月 再写 再挂 又隔了 ...
- bzoj 4127 线段树维护绝对值之和
因为d>=0,所以一个位置的数只会单调不降并且只会有一次穿过0. 用这个性质,我们我可在线段树中记录正数负数的个数和和,以及最大的负数以及答案. 修改操作:如果当前最大负数+d<=0,那么 ...
- [BZOJ 1018] [SHOI2008] 堵塞的交通traffic 【线段树维护联通性】
题目链接:BZOJ - 1018 题目分析 这道题就说明了刷题少,比赛就容易跪..SDOI Round1 Day2 T3 就是与这道题类似的..然而我并没有做过这道题.. 这道题是线段树维护联通性的经 ...
- BZOJ.1036 [ZJOI2008]树的统计Count ( 点权树链剖分 线段树维护和与最值)
BZOJ.1036 [ZJOI2008]树的统计Count (树链剖分 线段树维护和与最值) 题意分析 (题目图片来自于 这里) 第一道树链剖分的题目,谈一下自己的理解. 树链剖分能解决的问题是,题目 ...
随机推荐
- 5-python的封装与结构 - set集合
目录 1 封装与解构 1.1 封装 1.2 解构 1.3 Python3的解构 2 set类型 2.1 set的定义 2.2 set的基本操作 2.2.1 增加元素 2.2.2 删除元素 2.2.3 ...
- 关于linux系统如何实现fork的研究(一)【转】
转自:http://www.aichengxu.com/linux/4157180.htm 引言 fork函数是用于在linux系统中创建进程所使用,而最近看了看一个fork()调用是怎么从应用到gl ...
- keepalived主备切换后的arp问题【转】
使用keepalived的时候主机挂了,备机显示绑定了VIP.但是此时实际还是不能访问.其实就是网关的arp缓存没有刷新. 在服务器上执行一下就行了 arping -I eth0 -c 5 -s ...
- 全面了解 Nginx 主要应用场景
前言 本文只针对Nginx在不加载第三方模块的情况能处理哪些事情,由于第三方模块太多所以也介绍不完,当然本文本身也可能介绍的不完整,毕竟只是我个人使用过和了解到过得.所以还请见谅,同时欢迎留言交流 N ...
- 读书笔记 effective c++ Item 4 确保对象被使用前进行初始化
C++在对象的初始化上是变化无常的,例如看下面的例子: int x; 在一些上下文中,x保证会被初始化成0,在其他一些情况下却不能够保证.看下面的例子: class Point { int x,y; ...
- 用sar进行CPU利用率的分析
07:40:17 PM CPU %user %nice %system %iowait %steal %idle07:40:19 PM a ...
- 服务号使用微信网页授权(H5应用等)
获取授权准备 AppId 服务号已经认证且获取到响应接口权限 设置网页授权域名 公众号设置 - 功能设置 - 网页授权域名.注意事项: 回调页面域名或路径需使用字母.数字及"-"的 ...
- 初探Nginx架构
参考链接:http://tengine.taobao.org/book/chapter_02.html nginx在启动后,在unix系统中会以daemon的方式在后台运行,后台进程包含一个maste ...
- bash: composer: command not found
下载composer到本地:curl -sS https://getcomposer.org/installer | php 移动至系统服务:sudo mv composer.phar /usr/bi ...
- mysql 数据库备份及恢复
1.备份 # 导出数据库:mysqldump -u 用户名 -p 数据库名 > 导出的文件名mysqldump -–add-drop-table -uusername -ppassword da ...