• bzoj1018 [SHOI2008]堵塞的交通traffic——线段树


    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1018

    线段树竟然还可以这样用!

    维护的是一个矩形内部的连通情况,四个顶点之间有6种连通方式;

    因为连通情况具有可合并性,所以可以用线段树来维护!

    这篇博客写得很好:https://www.cnblogs.com/DUXT/p/6029815.html

    茅塞顿开之后看到这篇博客,觉得写得很好呢:https://www.cnblogs.com/MashiroSky/p/5973686.html

    我就是模仿上面第二篇博客写的,感觉自己对线段树的认识又加深了。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int const maxn=100005;
    int c,r1,r2,c1,c2;
    char ch[10];
    struct N{int U,D,u,d,l,r,p,q;}w[maxn<<2];
    struct T{int l,r;}tr[maxn<<2];
    void merge(N &k,N x,N y)//&
    {
        k.l=x.l|(x.u & k.U & y.l & k.D  &x.d);
        k.r=y.r|(y.u & k.U & x.r & k.D & y.d);
        k.u=(x.u & k.U & y.u)|(x.q & k.D & y.p);
        k.d=(x.d & k.D & y.d)|(x.p & k.U & y.q);
        k.p=(x.d & k.D & y.p)|(x.p & k.U & y.u);
        k.q=(x.u & k.U & y.q)|(x.q & k.D & y.d);
    }
    void build(int k,int l,int r)
    {
        tr[k].l=l; tr[k].r=r;
        if(l==r){w[k].U=w[k].D=w[k].u=w[k].d=1;return;}
        int mid=((l+r)>>1);
        build(k<<1,l,mid); build(k<<1|1,mid+1,r);
    //    merge(w[k],w[k<<1],w[k<<1|1]);//初始全不连通 
    }
    void updater(int k,int T,int x,int val)//同一行 
    {
        int l=tr[k].l,r=tr[k].r,mid=((l+r)>>1);
        if(x==mid)
        {
            if(T==1) w[k].U=val;
            else w[k].D=val;
            merge(w[k],w[k<<1],w[k<<1|1]);
            return;
        }
        if(x<=mid) updater(k<<1,T,x,val);
        else updater(k<<1|1,T,x,val);
        merge(w[k],w[k<<1],w[k<<1|1]);
    }
    void updatec(int k,int x,int val)//同一列
    {
        int l=tr[k].l,r=tr[k].r,mid=((l+r)>>1);
        if(l==r){w[k].l=w[k].r=w[k].p=w[k].q=val;return;}
        if(x<=mid) updatec(k<<1,x,val);
        else updatec(k<<1|1,x,val);
        merge(w[k],w[k<<1],w[k<<1|1]);
    }
    N query(int k,int l,int r)
    {
        int s=tr[k].l,t=tr[k].r,mid=((s+t)>>1);
        if(s>=l&&t<=r) return w[k];
        if(r<=mid) return query(k<<1,l,r);
        else if(l>mid) return query(k<<1|1,l,r);
        else
        {
            N ret=w[k];//保留 U,D 
            merge(ret,query(k<<1,l,r),query(k<<1|1,l,r));
            return ret;
        }
    }
    int main()
    {
        scanf("%d",&c);
        build(1,1,c);
        while(1)
        {
            scanf("%s",&ch);
            if(ch[0]=='E')return 0;
            scanf("%d%d%d%d",&r1,&c1,&r2,&c2);
            if(c1>c2) swap(c1,c2),swap(r1,r2);
            if(ch[0]=='O')
            {
                if(r1==r2)updater(1,r1,c1,1);
                else updatec(1,c1,1);
            }
            if(ch[0]=='C')
            {
                if(r1==r2)updater(1,r1,c1,0);
                else updatec(1,c1,0);
            }
            if(ch[0]=='A')
            {
                N l=query(1,1,c1),x=query(1,c1,c2),r=query(1,c2,c);
                int ans=0;
                if(r1==1&&r2==1)
                    ans=x.u|(l.r & x.d & r.l)|(x.q & r.l)|(l.r & x.p);
                if(r1==1&&r2==2)
                    ans=x.q|(l.r & x.p & r.l)|(l.r & x.d)|(x.u & r.l);
                if(r1==2&&r2==1)
                    ans=x.p|(l.r & x.q & r.l)|(l.r & x.u)|(x.d & r.l);
                if(r1==2&&r2==2)
                    ans=x.d|(l.r & x.u & r.l)|(x.p & r.l)|(l.r & x.q);
                if(ans) printf("Y
    ");
                else printf("N
    ");
            }
        }
    }
  • 相关阅读:
    6174问题
    阶乘的精确值
    小学生算术
    Primer回顾 数组和指针
    Primer回顾 标准库类型
    绪论
    字符串的存储
    条款39:明智而审慎的使用private继承
    条款34:区分接口继承和实现继承
    条款33:避免遮掩继承而来的名称
  • 原文地址:https://www.cnblogs.com/Zinn/p/9169122.html
Copyright © 2020-2023  润新知