bzoj 1018: [SHOI2008]堵塞的交通traffic

1018: [SHOI2008]堵塞的交通traffic

Description

  有一天,由于某种穿越现象作用,你来到了传说中的小人国。小人国的布局非常奇特,整个国家的交通系统可
以被看成是一个2行C列的矩形网格,网格上的每个点代表一个城市,相邻的城市之间有一条道路,所以总共有2C个
城市和3C-2条道路。 小人国的交通状况非常槽糕。有的时候由于交通堵塞,两座城市之间的道路会变得不连通,
直到拥堵解决,道路才会恢复畅通。初来咋到的你决心毛遂自荐到交通部某份差事,部长听说你来自一个科技高度
发达的世界,喜出望外地要求你编写一个查询应答系统,以挽救已经病入膏肓的小人国交通系统。 小人国的交通
部将提供一些交通信息给你,你的任务是根据当前的交通情况回答查询的问题。交通信息可以分为以下几种格式:
Close r1 c1 r2 c2:相邻的两座城市(r1,c1)和(r2,c2)之间的道路被堵塞了;Open r1 c1 r2 c2:相邻的两座城
市(r1,c1)和(r2,c2)之间的道路被疏通了;Ask r1 c1 r2 c2:询问城市(r1,c1)和(r2,c2)是否连通。如果存在一
条路径使得这两条城市连通,则返回Y,否则返回N;

Input

  第一行只有一个整数C,表示网格的列数。接下来若干行,每行为一条交通信息,以单独的一行“Exit”作为
结束。我们假设在一开始所有的道路都是堵塞的。我们保证 C小于等于100000,信息条数小于等于100000。

Output

  对于每个查询,输出一个“Y”或“N”。

Sample Input

2
Open 1 1 1 2
Open 1 2 2 2
Ask 1 1 2 2
Ask 2 1 2 2
Exit

Sample Output

Y
N

HINT

题解:

由于只有两行,我们可以在这两行里用线段树维护连通性。把一列的两个点看为整体,维护(i,j)即为维护i~j之间的连通性(注意,只在左右端点之间)。

维护的过程我就不说了,左上端点到右上端点,左上端点到右下端点等等,也够麻烦的。。。

不过事情还没完,一个点还可以通过其他路径到达目标点,比如左侧的点可以向左再向右走,但是这时它肯定经过它这一列的另外一个点,这个点能不能到它这一列的另外一个点可以在(1,L)中知道答案。

到此问题也就基本解决了(提一下,c++用函数返回数组真麻烦。。)

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
#define p1 (p<<1)
#define p2 (p<<1|1)
char s[15];
int n,i,x,y,x1,y1,t[400005][7],f[100005][3],ans[7],ansl[7],ansr[7];
int fans;
void renew(int a[7],int b[7],int x,int p,int mid)
{
    int c[7],i;
    c[1]=(a[1]|(a[3]&f[mid][1]&a[6]&f[mid][2]&b[1])|(a[4]&f[mid][1]&f[mid][2]&b[1]&a[5]));
    c[2]=((b[2]|(b[3]&f[mid][1]&f[mid][2]&a[2]&b[6])|(b[5]&f[mid][1]&f[mid][2]&a[2]&b[4])));
    c[3]=((a[3]&f[mid][1]&b[3])|(a[4]&f[mid][2]&b[5]));
    c[6]=((a[6]&f[mid][2]&b[6])|(a[5]&f[mid][1]&b[4]));
    c[4]=((a[3]&f[mid][1]&b[4])|(a[4]&f[mid][2]&b[6]));
    c[5]=((a[6]&f[mid][2]&b[5])|(a[5]&f[mid][1]&b[3]));
    for(i=1;i<=6;i++)
    {
        if(x==1) t[p][i]=c[i];else
        if(x==2) ansl[i]=c[i];else
        if(x==3) ans[i]=c[i];else
        ansr[i]=c[i];
    }
}
void build(int l,int r,int p)
{
    if(l==r)
    {
        t[p][3]=1;
        t[p][6]=1;
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,p1);
    build(mid+1,r,p2);
    renew(t[p1],t[p2],1,p,mid);
}
void update(int l,int r,int x,int y,int z,int k,int p)
{
    if(l==r)
    {
        if(z==0)
        {
            t[p][1]=k;
            t[p][2]=k;
            t[p][4]=k;
            t[p][5]=k;
        } else
        {
            f[l][y]=k;
        }
        return;
    }
    int mid=(l+r)>>1;
    if(x<=mid) update(l,mid,x,y,z,k,p1);else
    update(mid+1,r,x,y,z,k,p2);
    renew(t[p1],t[p2],1,p,mid);
}
void solve(int l,int r,int x,int y,int z,int p)
{
    int i;
    if(x<=l&&r<=y)
    {
        if(l==x)
        {
            for(i=1;i<=6;i++)
            {
                if(z==2) ansl[i]=t[p][i];else
                if(z==3) ans[i]=t[p][i];else
                ansr[i]=t[p][i];
            }
        } else
        {
            if(z==2) renew(ansl,t[p],z,0,l-1);else
            if(z==3) renew(ans,t[p],z,0,l-1);else
            renew(ansr,t[p],z,0,l-1);
        }
        return;
    }
    int mid=(l+r)>>1;
    if(x<=mid) solve(l,mid,x,y,z,p1);
    if(y>mid) solve(mid+1,r,x,y,z,p2);
}
int main()
{
    scanf("%d",&n);
    build(1,n,1);
    while(true)
    {
        scanf("%s",&s);
        if(s[0]=='E') break;
        if(s[0]=='O')
        {
            scanf("%d%d%d%d",&x,&y,&x1,&y1);
            if(y>y1)
            {
                swap(x,x1);
                swap(y,y1);
            }
            if(y==y1) update(1,n,y,0,0,1,1);else
            update(1,n,y,x,1,1,1);
        } else
        if(s[0]=='C')
        {
            scanf("%d%d%d%d",&x,&y,&x1,&y1);
            if(y>y1)
            {
                swap(x,x1);
                swap(y,y1);
            }
            if(y==y1) update(1,n,y,0,0,0,1);else
            update(1,n,y,x,1,0,1);
        } else
        {
            scanf("%d%d%d%d",&x,&y,&x1,&y1);
            if(y>y1)
            {
                swap(x,x1);
                swap(y,y1);
            }
            for(i=1;i<=6;i++)
            {
                ansl[i]=0;
                ans[i]=0;
                ansr[i]=0;
            }
            solve(1,n,1,y,2,1);
            solve(1,n,y,y1,3,1);
            solve(1,n,y1,n,4,1);
            fans=ans[x*2+x1];
            fans=fans|(ansl[2]&ans[(3-x)*2+x1])|(ansr[1]&ans[x*2+3-x1])|(ansl[2]&ansr[1]&ans[(3-x)*2+3-x1]);
            if(fans) printf("Y\n");else printf("N\n");
        }
    }
    return 0;
}

 

posted @ 2016-04-23 20:28  lwq12138  阅读(322)  评论(0编辑  收藏  举报