zoukankan      html  css  js  c++  java
  • BZOJ1018 堵塞的交通(线段树)

    题目很好明白,然后实现很神奇。首先如果考虑并查集的话,对于删边和加边操作我们无法同时进行。然后暴力分块的话,复杂度是O(n sqrt n) ,不是很优。于是看了题解,发现了线段树的神奇用途。

    我们维护每个矩形四个顶点的六个变量,分别是:

    g[0]:表示第一行左右端点的连通性。

    g[1]:表示第二行左右端点的连通性。

    g[2]:左上端点和左下端点的连通性。

    g[3]:右上端点和右下端点的连通性。

    g[4]:左上端点和右下端点的连通性。

    g[5]:左下端点和右上端点的连通性。

    这六个变量做好之后就可以合并矩形了。同样是这六个变量,合并的时候需要费点事,考虑一下各种情况。

    最后需要的一点就是可能出现的特殊情况,这样的怎么办?

    我们考虑全面即可,查询的时候不光查询一个区间,还需要查询两头的区间,然后判断是否会出现这种情况,就是我写的solve函数里面判断答案的后三种情况。 ——by VANE

    #include<bits/stdc++.h>
    using namespace std;
    const int N=100005;
    struct node{bool g[6];};
    int n;
    node s[5],t[N*4];
    bool m[N*4];
    int calc(int x,int y){return x*(n-1)+y;}
    void build(int rt,int l,int r)
    {
        if(l==r) {t[rt]=s[0];return;}
        int mid=l+r>>1;
        build(rt<<1,l,mid);
        build(rt<<1|1,mid+1,r);
    }
    node merge(node a,node b,bool x,bool y)
    {
        node c;
        c.g[0]=(a.g[0]&&x&&b.g[0])||(a.g[4]&&y&&b.g[5]);
        c.g[1]=(a.g[1]&&y&&b.g[1])||(a.g[5]&&x&&b.g[4]);
        c.g[2]=(a.g[2])||(a.g[0]&&x&&b.g[2]&&y&&a.g[1]);
        c.g[3]=(b.g[3])||(b.g[0]&&x&&a.g[3]&&y&&b.g[1]);
        c.g[4]=(a.g[0]&&x&&b.g[4])||(a.g[4]&&y&&b.g[1]);
        c.g[5]=(b.g[0]&&x&&a.g[5])||(b.g[5]&&y&&a.g[1]);
        return c;
    }
    void insert(int rt,int l,int r,int x,int y,int xx,int yy,bool c)
    {
        int mid=l+r>>1;
        if(x==xx&&y==mid)
        {
            m[calc(x,y)]=c;
            t[rt]=merge(t[rt<<1],t[rt<<1|1],m[calc(0,mid)],m[calc(1,mid)]);
            return;
        }
        else if(x!=xx&&l==r){t[rt]=s[c];return;}
        if(y<=mid) insert(rt<<1,l,mid,x,y,xx,yy,c);
        if(y>mid) insert(rt<<1|1,mid+1,r,x,y,xx,yy,c);
        t[rt]=merge(t[rt<<1],t[rt<<1|1],m[calc(0,mid)],m[calc(1,mid)]);
    }
    node query(int rt,int l,int r,int ll,int rr)
    {
        int mid=r+l>>1;
        if(l>=ll&&r<=rr) return t[rt];
        if(rr<=mid)return query(rt<<1,l,mid,ll,rr);
        if(ll>mid) return query(rt<<1|1,mid+1,r,ll,rr);
        return merge(query(rt<<1,l,mid,ll,rr),query(rt<<1|1,mid+1,r,ll,rr),m[calc(0,mid)],m[calc(1,mid)]);
    }
    void solve(int x,int y,int xx,int yy)
    {
        bool ans;
        s[2]=query(1,1,n,1,y);
        s[3]=query(1,1,n,y,yy);
        s[4]=query(1,1,n,yy,n);
        if(x==xx) ans=(s[3].g[x])||(s[2].g[3]&&s[3].g[4+x^1])||(s[4].g[2]&&s[3].g[4+x])||(s[2].g[3]&&s[4].g[2]&&s[3].g[x^1]);
        else ans=(s[3].g[4+x])||(s[2].g[3]&&s[3].g[x^1])||(s[4].g[2]&&s[3].g[x])||(s[2].g[3]&&s[3].g[4+x^1]&&s[4].g[2]);
        if(ans) puts("Y");
        else puts("N");
        
    }
    int main()
    {
        scanf("%d",&n);
        s[0]=(node){1,1,0,0,0,0};
        s[1]=(node){1,1,1,1,1,1};
        memset(t,0,sizeof t);
        memset(m,0,sizeof m);
        build(1,1,n);
        char ch[6];scanf("%s",ch);
        while(ch[0]!='E')
        {
            int x,y,xx,yy;scanf("%d%d%d%d",&x,&y,&xx,&yy);
            if(y>yy) swap(x,xx),swap(y,yy);
            x--;xx--;
            if(ch[0]=='O') insert(1,1,n,x,y,xx,yy,1);
            else if(ch[0]=='C') insert(1,1,n,x,y,xx,yy,0);
            else solve(x,y,xx,yy);
            scanf("%s",ch);
        }
    }
  • 相关阅读:
    Python 操作 MySQL数据库提示pymysql.err.InternalError: (1054, "Unknown column 'XXXXXXXXX' in 'where clause'")解决方法
    MySQL连接池不能查到刚写入的数据——连接池配置问题
    python 将字典转为bytes类型字典
    关于状态机的问题思考——什么时候达到新的状态?什么时候清除老状态?新状态与老状态之间的关系
    mysql 8.0.19 安装 及 端口修改
    sprintf printf 输出数据固定格式——数字前补零
    思维大爆炸
    IO点作为状态判断——一定要做软件“消抖”
    React-umi-request动态刷新Token功能实现及node.js 代码逻辑
    js测试题
  • 原文地址:https://www.cnblogs.com/nbwzyzngyl/p/8287935.html
Copyright © 2011-2022 走看看