zzzyc

导航

[SHOI2008]堵塞的交通traffic

线段树维护连通性。。。

通过分析我们可以发现,一个城市到另一个城市一共只有很少的几种情况

所以我们可以维护这个 2*X 矩形

判断其 从左上角到左下角

     左上角到右上角

     左上角到右下角

     左下角到右上角

     左下角到右下角

     右上角到右下角

            的连通性

通过得到的连通性再判断即可

呆码:

#include<iostream>
#include<cstdio>
using namespace std;

struct asd{
    bool luru,ldrd;
    bool lurd,ldru;
    bool luld,rurd;
    bool self[3];
} a[100010*4];
// l:left ; r:right ; u:up ; d:down
// 表示能否从一个角到另一个角 

int r1,r2,c1,c2,n;

inline asd pushup(asd x,asd y)
{
    asd ans;
    ans.luru=ans.ldrd=0;
    ans.lurd=ans.ldru=0;
    ans.luld=ans.rurd=0;
    ans.self[1]=y.self[1],ans.self[2]=y.self[2];
    if((x.luru && x.self[1] && y.luru) || (x.lurd && x.self[2] && y.ldru)) ans.luru=1;
    if((x.ldrd && x.self[2] && y.ldrd) || (x.ldru && x.self[1] && y.lurd)) ans.ldrd=1;
    if((x.luru && x.self[1] && y.lurd) || (x.lurd && x.self[2] && y.ldrd)) ans.lurd=1;
    if((x.ldrd && x.self[2] && y.ldru) || (x.ldru && x.self[1] && y.luru)) ans.ldru=1;
    if((x.luld) || (x.luru && x.self[1] && y.luld && x.self[2] && x.ldrd)) ans.luld=1;
    if((y.rurd) || (y.luru && x.self[1] && x.rurd && x.self[2] && y.ldrd)) ans.rurd=1;
    return ans;
}

inline void build(int rt,int l,int r)
{
    if(l==r)
    {
        a[rt].luru=a[rt].ldrd=1;
        return;
    }
    int mid=l+r>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
    a[rt]=pushup(a[rt<<1],a[rt<<1|1]);
}

inline void change1(int rt,int l,int r,int L,int k)
{
    if(l==r)
    {
        a[rt].lurd=a[rt].ldru=a[rt].luld=a[rt].rurd=k;
        return;
    }
    int mid=l+r>>1;
    if(L<=mid) change1(rt<<1,l,mid,L,k);
    else change1(rt<<1|1,mid+1,r,L,k);
    a[rt]=pushup(a[rt<<1],a[rt<<1|1]);
}

inline void change2(int rt,int l,int r,int L,int y,int k)
{
    if(l==r)
    {
        a[rt].self[y]=k;
        return;
    }
    int mid=l+r>>1;
    if(L<=mid) change2(rt<<1,l,mid,L,y,k);
    else change2(rt<<1|1,mid+1,r,L,y,k);
    a[rt]=pushup(a[rt<<1],a[rt<<1|1]);
}

inline asd query(int rt,int l,int r,int L,int R)
{
    if(L<=l && r<=R) { return a[rt]; }
    int mid=l+r>>1;
    asd ans1,ans2;
    bool left=0,right=0;
    if(L<=mid) ans1=query(rt<<1,l,mid,L,R),left=1;
    if(R>mid) ans2=query(rt<<1|1,mid+1,r,L,R),right=1;
    if(left==1 && right==1) return pushup(ans1,ans2);
    else return left==1 ? ans1 : ans2;
}

inline bool check()
{
    if(c1>c2) { swap(c1,c2); swap(r1,r2); }
    asd pre=query(1,1,n,1,c1);
    asd now=query(1,1,n,c1,c2);
    asd nxt=query(1,1,n,c2,n);
    if(r1==r2)
    {
        if(r1==1 && ((now.luru) || (pre.rurd && now.ldru) || (nxt.luld && now.lurd) || (pre.rurd && now.ldrd && nxt.luld))) return 1;
        if(r1==2 && ((now.ldrd) || (pre.rurd && now.lurd) || (nxt.luld && now.ldru) || (pre.rurd && now.luru && nxt.luld))) return 1;
    }
    else
    {
        if(r1==1 && ((now.lurd) || (pre.rurd && now.ldrd) || (nxt.luld && now.luru) || (pre.rurd && now.ldru && nxt.luld))) return 1;
        if(r1==2 && ((now.ldru) || (pre.rurd && now.luru) || (nxt.luld && now.ldrd) || (pre.rurd && now.lurd && nxt.luld))) return 1;
    }
    return 0;
}

int main()
{
    scanf("%d",&n);
    build(1,1,n);
    while(1)
    {
        char ch[10]; scanf("%s",ch);
        if(ch[0]=='E') break;
        scanf("%d%d%d%d",&r1,&c1,&r2,&c2);
        if(ch[0]=='O')
        {
            if(c1==c2) change1(1,1,n,c1,1);
            else change2(1,1,n,min(c1,c2),r1,1);
        }
        if(ch[0]=='C')
        {
            if(c1==c2) change1(1,1,n,c1,0);
            else change2(1,1,n,min(c1,c2),r1,0);
        }
        if(ch[0]=='A')
        {
            if(check()) printf("Y\n");
            else printf("N\n");
        }
    }
    return 0;
}
代码

 

posted on 2018-08-26 08:41  zzzyc  阅读(216)  评论(0编辑  收藏  举报