堵塞的交通traffic(线段树神题)

传送门

题意:有一个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("Y\n");
            else printf("N\n");
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值