概述
传送门
题意:有一个2*n的方格,每个方格会与周围的格子连接,最开始路是断开的,给你3种操作,输出询问操作的格子是否连通;
题解:线段数神题,也是李超ppt中的例题之一,用线段树维护当前2*len长度的方格的联通性,将方格4个角的联通性与中间格子的联通性记录下来,当前区间的联通性可以由子区间得到,例如:要得到当前区间左上和右下的连通性,可以先看左区间的连通性,在通过中间的方格中转在考录右区间的连通性性得到左上和右下的连通性(具体看代码),查询时要将当前方格分为3个部分,即[1,r1],[r1,r2],[r2,n],因为在进行加或者减操作时,不能更新到根节点所以对于当前的查询点是可以先向左或右在在到目标节点,或者继续在右边节点在跳到目标节点。
AC代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<math.h>
#include<stdlib.h>
#define ll long long
#define lowbit(x) x&(-x)
#define ls k<<1
#define rs k<<1|1
using namespace std;
const int maxn=1e5+5;
const int mod=1e9+7;
int read(){
char c;int x=0,y=1;while(c=getchar(),(c<'0'||c>'9')&&c!='-');
if(c=='-') y=-1;else x=c-'0';while(c=getchar(),c>='0'&&c<='9')
x=x*10+c-'0';return x*y;
}
/*
* 1 ************** 2
* **************
* **************
* 3 ************** 4
*/
struct node{
int m1,m2,c12,c13,c14,c24,c32,c34;//cij,i和j的联通形,mi,中间第i行的联通性
};
node tree[maxn*4];
void pushup(node &now,node l,node r){
now.c12=((now.m1&&l.c12&&r.c12)||(now.m2&&l.c14&&r.c32));
now.c14=((now.m1&&l.c12&&r.c14)||(now.m2&&l.c14&&r.c34));
now.c13=l.c13||(l.c12&&now.m1&&r.c13&&now.m2&&l.c34);
now.c24=r.c24||(r.c12&&now.m1&&l.c24&&now.m2&&r.c34);
now.c34=((now.m1&&l.c32&&r.c14)||(now.m2&&l.c34&&r.c34));
now.c32=((now.m1&&l.c32&&r.c12)||(now.m2&&l.c34&&r.c32));
}
void build(int l,int r,int k){
tree[k].m1=tree[k].m2=0;
tree[k].c12=tree[k].c13=tree[k].c14=tree[k].c24=tree[k].c32=tree[k].c34=0;
if(l==r){
tree[k].c12=tree[k].c34=tree[k].m1=tree[k].m2=1;
return ;
}
int mid=(l+r)>>1;
build(l,mid,ls);
build(mid+1,r,rs);
}
void modify1(int l,int r,int k,int va,int wi){//同列
if(l==r){
tree[k].c13=tree[k].c14=tree[k].c32=tree[k].c24=va;
return ;
}
int mid=(l+r)>>1;
if(mid>=wi) modify1(l,mid,ls,va,wi);
else modify1(mid+1,r,rs,va,wi);
pushup(tree[k],tree[ls],tree[rs]);
}
void modify2(int l,int r,int k,int va,int wi,int p){//同行
int mid=(l+r)>>1;
if(mid==wi){
if(p) tree[k].m2=va;
else tree[k].m1=va;
pushup(tree[k],tree[ls],tree[rs]);
return ;
}
if(mid>wi) modify2(l,mid,ls,va,wi,p);
else modify2(mid+1,r,rs,va,wi,p);
pushup(tree[k],tree[ls],tree[rs]);
}
node query(int l,int r,int k,int l1,int r1){
if(l>=l1&&r<=r1) return tree[k];
int mid=(l+r)>>1;
if(mid>=r1) return query(l,mid,ls,l1,r1);
else if(mid+1<=l1) return query(mid+1,r,rs,l1,r1);
else{
node x=tree[k];
pushup(x,query(l,mid,ls,l1,r1),query(mid+1,r,rs,l1,r1));
return x;
}
}
int main( )
{
int n=read();
build(1,n,1);
char s[10];
int r1,c1,r2,c2;
while(~scanf("%s",s)){
if(s[0]=='E') break;
r1=read(),c1=read(),r2=read(),c2=read();
if(c1>c2) swap(r1,r2),swap(c1,c2);
if(s[0]=='O'){ if(c1==c2) modify1(1,n,1,1,c1); else modify2(1,n,1,1,c1,r1-1);}
if(s[0]=='C'){if(c1==c2) modify1(1,n,1,0,c1); else modify2(1,n,1,0,c1,r1-1);}
if(s[0]=='A'){
node l=query(1,n,1,1,c1),x=query(1,n,1,c1,c2),r=query(1,n,1,c2,n);
int ans=0;
if(r1==1&&r2==1) ans=x.c12||(l.c24&&x.c32)||(r.c13&&x.c14)||(l.c24&&x.c34&&r.c13);
if(r1==2&&r2==2) ans=x.c34||(l.c24&&x.c14)||(r.c13&&x.c32)||(l.c24&&x.c12&&r.c13);
if(r1==1&&r2==2) ans=x.c14||(l.c24&&x.c34)||(r.c13&&x.c12)||(l.c24&&x.c32&&r.c13);
if(r1==2&&r2==1) ans=x.c32||(l.c24&&x.c12)||(r.c13&&x.c34)||(l.c24&&x.c14&&r.c13);
if(ans) printf("Yn");
else printf("Nn");
}
}
}
最后
以上就是微笑帅哥为你收集整理的堵塞的交通traffic(线段树神题)的全部内容,希望文章能够帮你解决堵塞的交通traffic(线段树神题)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复