• bzoj1018 [SHOI2008]堵塞的交通traffic


    题目链接

    分析:
    这道题的题解很长,所以就不粘题面了,我们一点一点讲明白这道题

    很荣幸,我看了题面之后
    想到了这道题

    可以很高兴的发现10w是线段树能够承受的范围
    我们可以利用线段树维护连通性,每个节点内我们要维护6个信息,分别表示连通性:
    这里写图片描述
    读入完成后,我们面临的第一个问题就是道路的状态改变

    这就牵扯到了一个change函数

    这里写图片描述

    link函数中,

    我们只维护了向下走的直接连通性
    至于其他的连通性,我们在update函数中完成
    这里写图片描述
    这里写图片描述

    ask函数

    这次默认列数小的点为第一个点
    这两个点就把整个序列分成了3个部分 :1~c1,c1~c2,c2~n
    我们通过get函数求出这三个部分的连通情况
    之后就是特判了
    这里写图片描述

    tip

    题目中的(r1,c1)
    表示的是第r1行,第c1列

    第一次交上去:WA
    之后就是一句一句的排查,
    终于把问题锁定在了ask函数中
    一开始以为是特判的问题,但是查了半天也没有什么异常

    最后才发现是在get的时候
    手残把c1,c2写错了

    这里写代码片
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    
    using namespace std;
    
    const int N=100010;
    struct node{
        bool x[2],y[2],z[2];
    };
    node t[N<<2];
    int n,r1,r2,c1,c2;
    bool a[N][2][2];
    char opt[10];
    int dx[3]={-1,0,1};   //每个点只能与三个点直接相连 
    int dy[3]={0,1,0};
    
    void build(int bh,int l,int r)
    {
        if (l==r)
        {
            t[bh].x[0]=1;  //横向 
            t[bh].x[1]=1;
            return;
        }  
        int mid=(l+r)>>1;
        build(bh<<1,l,mid);
        build(bh<<1|1,mid+1,r);
    }
    
    void update(node &bh,node &lc,node &rc,int mid)
    {
        bh.x[0]=(lc.x[0]&&a[mid][0][0]&&rc.x[0])||(lc.z[0]&&a[mid][1][0]&&rc.z[1]);  //左上-右上 
        bh.x[1]=(lc.x[1]&&a[mid][1][0]&&rc.x[1])||(lc.z[1]&&a[mid][0][0]&&rc.z[0]);  //左下-右下 
        bh.y[0]=lc.y[0]||(lc.x[0]&&a[mid][0][0]&&rc.y[0]&&a[mid][1][0]&&lc.x[1]);  //左上-左下
        bh.y[1]=rc.y[1]||(rc.x[0]&&a[mid][0][0]&&lc.y[1]&&a[mid][1][0]&&rc.x[1]);  //右上-右下
        bh.z[0]=(lc.x[0]&&a[mid][0][0]&&rc.z[0])||(lc.z[0]&&a[mid][1][0]&&rc.x[1]);  //左上-右下 
        bh.z[1]=(lc.x[1]&&a[mid][1][0]&&rc.z[1])||(lc.z[1]&&a[mid][0][0]&&rc.x[0]);  //左下-右上 
    }
    
    void link(int bh,int l,int r,int p)
    {
        if (l==r)  //单点修改 
        {
            t[bh].y[0]=t[bh].y[1]=t[bh].z[0]=t[bh].z[1]=a[p][0][1];
            t[bh].x[0]=t[bh].x[1]=1;
            return;
        } 
        int mid=(l+r)>>1;
        if (p<=mid) link(bh<<1,l,mid,p);
        else link(bh<<1|1,mid+1,r,p);
        update(t[bh],t[bh<<1],t[bh<<1|1],mid);
    }
    
    void change(bool o)   
    {
        int d;
        for (int i=0;i<3;i++)
            if (c1+dx[i]==c2&&r1+dy[i]==r2)   //两个点的相对位置
                d=i;
        if (d==0) a[c2][r2][0]=o,link(1,1,n,c2); //1-->2 左 
        else if (d==1) a[c1][0][1]=o,link(1,1,n,c1); //下 
        else a[c1][r1][0]=o,link(1,1,n,c1); //右 
    }
    
    void get(node &p,int bh,int L,int R,int l,int r)
    {
        if (L>=l&&R<=r) {p=t[bh];return;}
        int mid=(L+R)>>1;
        if (r<=mid) get(p,bh<<1,L,mid,l,r);
        else if (l>mid) get(p,bh<<1|1,mid+1,R,l,r);
        else
        {
            node t1,t2;
            get(t1,bh<<1,L,mid,l,r);
            get(t2,bh<<1|1,mid+1,R,l,r);
            update(p,t1,t2,mid);
        }
    }
    
    void ask()
    {
        if(c1>c2) swap(r1,r2),swap(c1,c2);
        node p1,p2,p3;
        get(p1,1,1,n,1,c1);
        get(p2,1,1,n,c1,c2);
        get(p3,1,1,n,c2,n);
        if (r1==r2)
        {
            if (r1==0)
            {
                if (p2.x[0]||(p1.y[1]&&p2.x[1]&&p3.y[0])||(p1.y[1]&&p2.z[1])||(p3.y[0]&&p2.z[0])) printf("Y
    ");
                else printf("N
    ");
            }
            else
            {
                if (p2.x[1]||(p2.x[0]&&p1.y[1]&&p3.y[0])||(p1.y[1]&&p2.z[0])||(p3.y[0]&&p2.z[1])) printf("Y
    ");
                else printf("N
    ");
            }
        }
        else
        {
            if (r1==0)
            {
                if (p2.z[0]||(p1.y[1]&&p2.x[1])||(p2.x[0]&&p3.y[0])) printf("Y
    ");
                else printf("N
    ");
            }
            else
            {
                if (p2.z[1]||(p1.y[1]&&p2.x[0])||(p3.y[0]&&p2.x[1])) printf("Y
    ");
                else printf("N
    ");
            }
        }
    }
    
    int main()
    {
        scanf("%d",&n);
        build(1,1,n);
        scanf("%s",&opt);
        while (opt[0]!='E')
        {
            int a,b,c,d;
            scanf("%d%d%d%d",&r1,&c1,&r2,&c2);
            r1--;r2--;
            if (r1>r2) swap(c1,c2),swap(r1,r2);   //点从上到下编号 
            if (opt[0]=='O') change(1);
            else if (opt[0]=='C') change(0);
            else ask();
            scanf("%s",&opt);
        }
        return 0;
    }
  • 相关阅读:
    Android之旅十六 android中各种资源的使用
    XTU OJ 1207 Welcome to XTCPC (字符串签到题)
    scala并发编程原生线程Actor、Case Class下的消息传递和偏函数实战
    【云图】怎样设置支付宝里的家乐福全国连锁店地图?
    怎样在QML中使用multitouch
    软件project师周兆熊给IT学子的倾情奉献
    Linux系统下怎样配置SSH?怎样开启SSH?
    数学之路-python计算实战(4)-Lempel-Ziv压缩(2)
    Day5上午解题报告
    一份只有巨佬才能看懂的代码
  • 原文地址:https://www.cnblogs.com/wutongtong3117/p/7673189.html
Copyright © 2020-2023  润新知