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 (树链剖分 线段树维护和与最值) 题意分析 (题目图片来自于 这里) 第一道树链剖分的题目,谈一下自己的理解. 树链剖分能解决的问题是,题目 ...
随机推荐
- javascript经典小游戏代码集合
http://www.jb51.net/Special/349.htm
- thinkphp crud实例代码
class IndexAction extends Action { // 查询数据 public function index() { $Form = M("Form"); $l ...
- flask插件系列之SQLAlchemy实用技巧
下面记录一下SQLAlchemy使用的技巧. 在多模块下定义models 如果由多个蓝图下读定义了model模块,在初始化的时候需要加载到上下文中. 当使用flask_Migrate迁移数据库的时候, ...
- tera term通过ttl脚本 自动连接服务器(转自http://www.cnblogs.com/wxb0328/p/teraterm.html)
转自http://www.cnblogs.com/wxb0328/p/teraterm.html 在现在的这个公司一直使用tera term来远程连接服务器,感觉很方便,特别是它的ttl脚本配置的自动 ...
- 152.Maximum Product Subarray---dp---连续子数组的最大乘积---《编程之美》2.13子数组的最大乘积
题目链接:https://leetcode.com/problems/maximum-product-subarray/description/ 题目大意:给出一串数组,找出连续子数组中乘积最大的子数 ...
- openjudge-NOI 2.6基本算法之动态规划 专题题解目录
1.1759 最长上升子序列 2.1768 最大子矩阵 3.1775 采药 4.1808 公共子序列 5.1944 吃糖果 6.1996 登山 7.2000 最长公共子上升序列 8.2718 移动路线 ...
- 转:google测试分享-问题和挑战
原文: http://blog.sina.com.cn/s/blog_6cf812be0102vxer.html 前言:这个系列分享的内容大部分都是出自于<google是如何测试的>的书, ...
- WireShark出现The NPF driver isn't running的问题
昨天开始尝试装上了wireshark网络监视软件,可是今天打开去总是出现“The NPF driver isn't running.You may have trouble capturing or ...
- HDU 4553 约会安排(线段树区间合并+双重标记)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4553 题目大意:就是有三种操作: ①DS x,安排一段长度为x的空闲时间跟屌丝一起,输出这段时间的起点 ...
- python和C语言的差别
之前在公司一直做的是C语言的开发,然后做的都是业务方面的东西,做的是sdk,因为最近在找工作,然后今天面试的时候被问到C语言和Python的区别,自己只是简单的说了C是静态语言,在变量在使用前进行声明 ...