bzoj 1018 堵塞的交通|线段树维护连通性

很久之前听泽神说过这道题,今天终于下定决心写了

维护两个横,两个竖,两个斜的连通性h[2],s[2],x[2]。转移如下表(a为左子树,b为右子树,t为目标子树)

bzoj 1018 堵塞的交通|线段树维护连通性_第1张图片

 查询时要考虑绕了一圈的情况,即[1,l][l,r][r,n]三个区间的连通性

最后竟然是close的时候把边赋成了1

1018: [SHOI2008]堵塞的交通traffic
Time Limit: 3 Sec  Memory Limit: 162 MB
Submit: 2233  Solved: 695
[Submit][Status][Discuss]
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”作为结束。我们假设在一开始所有的道路都是堵塞的。 对30%测试数据,我们保证C小于等于1000,信息条数小于等于1000; 对100%测试数据,我们保证 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

 


#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
 
#define md
#define ll long long
#define inf (int) 1e9
#define eps 1e-8
#define N 100010
using namespace std;
struct tree {int l,r; bool s[2],h[2],x[2];} tr[4*N];
tree T,left,right;
bool line[N],road[2][N];
void outit(tree a)
{
    printf("%d %d S: %d %d H: %d %d X: %d %d\n",a.l,a.r,a.s[0],a.s[1],a.h[0],a.h[1],a.x[0],a.x[1]);
}
tree update(tree a,tree b)
{
    tree t; t.l=a.l; t.r=b.r;
    if (a.s[0]||line[a.l]) t.s[0]=1; else t.s[0]=0;
    if (b.s[1]||line[b.r]) t.s[1]=1; else t.s[1]=0;
    t.h[0]=t.h[1]=t.x[0]=t.x[1]=0;
    if (a.h[0]&&road[0][a.r]) //ah0 r0-l0
    {
        if (b.s[0]&&a.h[1]&&road[1][a.r]) t.s[0]=1;
        if (b.h[0]) t.h[0]=1;
        if (b.x[0]) t.x[0]=1;
    }
    if (a.x[0]&&road[1][a.r])//ax0 r1-l1
    {
        if (b.x[1]) t.h[0]=1;
        if (b.h[1]) t.x[0]=1;
    }
    if (a.h[1]&&road[1][a.r])//ah1 r1-l1
    {
        if (b.x[1]) t.x[1]=1;
        if (b.h[1]) t.h[1]=1;
    }
    if (a.x[1]&&road[0][a.r])//ax1 r0-l0
    {
        if (b.h[0]) t.x[1]=1;
        if (b.x[0]) t.h[1]=1;
    }
    if (a.s[1]&&b.h[0]&&b.h[1]&&road[0][a.r]&&road[1][a.r]) t.s[1]=1;
    return t;
}
    
    
    
void build(int i,int l,int r)
{
    tr[i].l=l; tr[i].r=r;
    if (l==r) { tr[i].h[0]=tr[i].h[1]=1; return; }
    int mid=(l+r)>>1;
    build(2*i,l,mid); build(2*i+1,mid+1,r);
    tr[i]=update(tr[2*i],tr[2*i+1]);
}
void newline(int i)
{
    int pos=tr[i].l;
    if (line[pos]) tr[i].s[0]=tr[i].s[1]=tr[i].x[0]=tr[i].x[1]=1;
          else tr[i].s[0]=tr[i].s[1]=tr[i].x[0]=tr[i].x[1]=0;
    tr[i].h[0]=tr[i].h[1]=1;   
}
void modify(int i,int l,int r)
{
    if (tr[i].l==tr[i].r) { newline(i); return;}
    int mid=(tr[i].l+tr[i].r)>>1;
    if (r<=mid) modify(2*i,l,r);
    if (mid+1<=l) modify(2*i+1,l,r);
    tr[i]=update(tr[2*i],tr[2*i+1]);
}
tree query(int i,int l,int r)
{
    //printf("query: %d %d, now: %d L %d R %d\n",l,r,i,tr[i].l,tr[i].r);
    if (l<=tr[i].l&&tr[i].r<=r) return tr[i];
    int mid=(tr[i].l+tr[i].r)>>1;
    if (r<=mid) return query(2*i,l,r);
    if (mid+1<=l) return query(2*i+1,l,r);
    return update(query(2*i,l,r),query(2*i+1,l,r));
}
int main()
{
    int n; char st[10];
    int x1,y1,x2,y2;
    scanf("%d",&n);
    build(1,1,n);
    while (1)
    {
        scanf("%s",st);
        if (st[0]=='O')
        {
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            x1--; x2--;
            if (y1>y2) { swap(x1,x2); swap(y1,y2); }
            if (x1==x2)
            {
                road[x1][min(y1,y2)]=1;
                modify(1,y1,y2);
            }
            else
            {
                line[y1]=1;
                modify(1,y1,y2);
            }
        }
             
        else if (st[0]=='C')
        {
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            x1--; x2--;
            if (y1>y2) { swap(x1,x2); swap(y1,y2); }
            if (x1==x2)
            {
                road[x1][min(y1,y2)]=0;
                modify(1,y1,y2);
            }
            else
            {
                line[y1]=0;
                modify(1,y1,y2);
            }
        }
        else if (st[0]=='A')
        {
            bool ans=0;
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            x1--; x2--;
            if (y1>y2) { swap(x1,x2); swap(y1,y2); }
            T=query(1,y1,y2),left=query(1,1,min(y1,y2)),right=query(1,max(y1,y2),n);
            if (y1==y2)//同一列
            {
                ans=T.s[0];
                if (left.s[1]||right.s[0]) ans|=1;
            }
            else
              if (x1==x2) //同一行
              {
                  ans=T.h[x1];
                  bool L=0,R=0;
                  if (left.s[1]) L=1;
                  if (right.s[0]) R=1;
                  if ((L&&T.x[x1^1])||(R&&T.x[x1])||(L&&R&&T.h[x1^1])) ans=1;
              }
              else //一上一下
              {
                ans=T.x[x1];
                bool L=0,R=0;
                if (left.s[1]) L=1;
                if (right.s[0]) R=1;
                if ((L&&T.h[x1^1])||(R&&T.h[x1])||(L&&R&&T.x[x1^1])) ans=1;
              }
            if (ans) printf("Y\n"); else printf("N\n");
        }
        else break;/*
        if (st[0]!='A') continue;
        printf("road:\n");
        for (int i=1;i<=n;i++) printf(" %d %d \\",road[0][i],road[1][i]); printf("\n");
        printf("T: "); outit(T);
        for (int i=1;i<=15;i++) outit(tr[i]); printf("\n");*/
    }
    return 0;
}

你可能感兴趣的:(bzoj 1018 堵塞的交通|线段树维护连通性)