博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ1018 堵塞的交通(线段树)
阅读量:4678 次
发布时间:2019-06-09

本文共 2771 字,大约阅读时间需要 9 分钟。

题目很好明白,然后实现很神奇。首先如果考虑并查集的话,对于删边和加边操作我们无法同时进行。然后暴力分块的话,复杂度是O(n sqrt n) ,不是很优。于是看了题解,发现了线段树的神奇用途。

我们维护每个矩形四个顶点的六个变量,分别是:

g[0]:表示第一行左右端点的连通性。

g[1]:表示第二行左右端点的连通性。

g[2]:左上端点和左下端点的连通性。

g[3]:右上端点和右下端点的连通性。

g[4]:左上端点和右下端点的连通性。

g[5]:左下端点和右上端点的连通性。

这六个变量做好之后就可以合并矩形了。同样是这六个变量,合并的时候需要费点事,考虑一下各种情况。

最后需要的一点就是可能出现的特殊情况,这样的怎么办?

我们考虑全面即可,查询的时候不光查询一个区间,还需要查询两头的区间,然后判断是否会出现这种情况,就是我写的solve函数里面判断答案的后三种情况。 ——by VANE

#include
using namespace std;const int N=100005;struct node{
bool g[6];};int n;node s[5],t[N*4];bool m[N*4];int calc(int x,int y){
return x*(n-1)+y;}void build(int rt,int l,int r){ if(l==r) {t[rt]=s[0];return;} int mid=l+r>>1; build(rt<<1,l,mid); build(rt<<1|1,mid+1,r);}node merge(node a,node b,bool x,bool y){ node c; c.g[0]=(a.g[0]&&x&&b.g[0])||(a.g[4]&&y&&b.g[5]); c.g[1]=(a.g[1]&&y&&b.g[1])||(a.g[5]&&x&&b.g[4]); c.g[2]=(a.g[2])||(a.g[0]&&x&&b.g[2]&&y&&a.g[1]); c.g[3]=(b.g[3])||(b.g[0]&&x&&a.g[3]&&y&&b.g[1]); c.g[4]=(a.g[0]&&x&&b.g[4])||(a.g[4]&&y&&b.g[1]); c.g[5]=(b.g[0]&&x&&a.g[5])||(b.g[5]&&y&&a.g[1]); return c;}void insert(int rt,int l,int r,int x,int y,int xx,int yy,bool c){ int mid=l+r>>1; if(x==xx&&y==mid) { m[calc(x,y)]=c; t[rt]=merge(t[rt<<1],t[rt<<1|1],m[calc(0,mid)],m[calc(1,mid)]); return; } else if(x!=xx&&l==r){t[rt]=s[c];return;} if(y<=mid) insert(rt<<1,l,mid,x,y,xx,yy,c); if(y>mid) insert(rt<<1|1,mid+1,r,x,y,xx,yy,c); t[rt]=merge(t[rt<<1],t[rt<<1|1],m[calc(0,mid)],m[calc(1,mid)]);}node query(int rt,int l,int r,int ll,int rr){ int mid=r+l>>1; if(l>=ll&&r<=rr) return t[rt]; if(rr<=mid)return query(rt<<1,l,mid,ll,rr); if(ll>mid) return query(rt<<1|1,mid+1,r,ll,rr); return merge(query(rt<<1,l,mid,ll,rr),query(rt<<1|1,mid+1,r,ll,rr),m[calc(0,mid)],m[calc(1,mid)]);}void solve(int x,int y,int xx,int yy){ bool ans; s[2]=query(1,1,n,1,y); s[3]=query(1,1,n,y,yy); s[4]=query(1,1,n,yy,n); if(x==xx) ans=(s[3].g[x])||(s[2].g[3]&&s[3].g[4+x^1])||(s[4].g[2]&&s[3].g[4+x])||(s[2].g[3]&&s[4].g[2]&&s[3].g[x^1]); else ans=(s[3].g[4+x])||(s[2].g[3]&&s[3].g[x^1])||(s[4].g[2]&&s[3].g[x])||(s[2].g[3]&&s[3].g[4+x^1]&&s[4].g[2]); if(ans) puts("Y"); else puts("N"); }int main(){ scanf("%d",&n); s[0]=(node){
1,1,0,0,0,0}; s[1]=(node){
1,1,1,1,1,1}; memset(t,0,sizeof t); memset(m,0,sizeof m); build(1,1,n); char ch[6];scanf("%s",ch); while(ch[0]!='E') { int x,y,xx,yy;scanf("%d%d%d%d",&x,&y,&xx,&yy); if(y>yy) swap(x,xx),swap(y,yy); x--;xx--; if(ch[0]=='O') insert(1,1,n,x,y,xx,yy,1); else if(ch[0]=='C') insert(1,1,n,x,y,xx,yy,0); else solve(x,y,xx,yy); scanf("%s",ch); }}

 

转载于:https://www.cnblogs.com/nbwzyzngyl/p/8287935.html

你可能感兴趣的文章
python学习笔记(十五)-异常处理
查看>>
路径+DataRow+SqlPara防止sql注入
查看>>
Internet History, Technology and Security (Week5.1)
查看>>
MySQL查询in操作 查询结果按in集合顺序显示_Mysql_脚本之家
查看>>
解释型语言与编译型语言
查看>>
redis主从复制
查看>>
SQLite之登录注册
查看>>
Linux就该这么学(3)-管道符、重定向与环境变量(学习笔记)
查看>>
asm335x系列adc和触摸屏驱动(转)
查看>>
菜鸟nginx源代码剖析数据结构篇(八) 缓冲区链表ngx_chain_t
查看>>
Nginx基础教程
查看>>
good
查看>>
JavaScript之isNaN()函数讲解
查看>>
如何培养自己的管理才能?
查看>>
从App Store上获取已经上架的App版本信息
查看>>
SpringMvc实现日期转换
查看>>
Android稳定性测试之Log分析
查看>>
WPF中使用ObjectDataProvider绑定方法
查看>>
万能数据库查询分析器中文版本《DB查询分析器》几年来在“中关村在线”首次大榜小榜都能够榜上有名...
查看>>
孔明灯-噪点插画
查看>>