• CDOJ 1071 秋实大哥下棋 线段树


    分析:运用扫描线,先从左到右扫描,用纵坐标进行建树,

             随着扫描线的右向右移动。不断更新横坐标小于扫描线的车

             更新的时候  在树中更新车的纵坐标的位置,把该位置的值变成该车的横坐标

             线段树维护的是区间最大值和最小值

             这样每到一个矩形区域的右边界,查询该区间的纵坐标区间内的最大值和最小值

             如果最大值小于右边界,最小值大于左边界

             那么这个矩形区域内每一行都可以被矩形区域内的车覆盖,标记一下

             同理,从下到上扫描,可以找到符合条件的矩形

            

    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<cstdlib>
    #include<algorithm>
    #include<vector>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    const int N=2e5+5;
    int n,m,k,q;
    struct Rec
    {
        int x1,x2,y1,y2,id;
        bool operator<(const Rec &e)const
        {
            return x2<e.x2;
        }
    } o[N];
    bool cmp1(Rec a,Rec b)
    {
        return a.x2<b.x2;
    }
    bool cmp2(Rec a,Rec b)
    {
        return a.y2<b.y2;
    }
    struct Point
    {
        int x,y;
    } p[N];
    bool cmp3(Point a,Point b)
    {
        return a.x<b.x;
    }
    bool cmp4(Point a,Point b)
    {
        return a.y<b.y;
    }
    int c[N<<1],b[N<<1];
    void build(int rt,int l,int r)
    {
        b[rt]=c[rt]=N;
        if(l==r)return;
        int mid=(l+r)>>1;
        build(rt*2,l,mid);
        build(rt*2+1,mid+1,r);
    }
    void pushup(int rt)
    {
        c[rt]=min(c[rt*2],c[rt*2+1]);
        b[rt]=max(b[rt*2],b[rt*2+1]);
    }
    void update(int rt,int l,int r,int pos,int t)
    {
        if(l==r)
        {
            b[rt]=c[rt]=t;
            return;
        }
        int mid=(l+r)>>1;
        if(pos<=mid)update(rt*2,l,mid,pos,t);
        else update(rt*2+1,mid+1,r,pos,t);
        pushup(rt);
    }
    int querymin(int rt,int l,int r,int x,int y)
    {
        if(x<=l&&r<=y)
            return c[rt];
        int res=N;
        int mid=(l+r)>>1;
        if(x<=mid)res=min(res,querymin(rt*2,l,mid,x,y));
        if(y>mid)res=min(res,querymin(rt*2+1,mid+1,r,x,y));
        return res;
    }
    int querymax(int rt,int l,int r,int x,int y)
    {
        if(x<=l&&r<=y)
            return b[rt];
        int res=-1;
        int mid=(l+r)>>1;
        if(x<=mid)res=max(res,querymax(rt*2,l,mid,x,y));
        if(y>mid) res=max(res,querymax(rt*2+1,mid+1,r,x,y));
        return res;
    }
    bool ans[N];
    int main()
    {
        scanf("%d%d%d%d",&n,&m,&k,&q);
        for(int i=1; i<=k; ++i)
            scanf("%d%d",&p[i].x,&p[i].y);
        for(int i=1; i<=q; ++i)
            scanf("%d%d%d%d",&o[i].x1,&o[i].y1,&o[i].x2,&o[i].y2),o[i].id=i;
        sort(p+1,p+1+k,cmp3);
        sort(o+1,o+1+q,cmp1);
        int cnt=1;
        build(1,1,m);
        for(int i=1; i<=q; ++i)
        {
            for(; cnt<=k&&p[cnt].x<=o[i].x2; ++cnt)
                update(1,1,m,p[cnt].y,p[cnt].x);
            int a1=querymin(1,1,m,o[i].y1,o[i].y2);
            int a2=querymax(1,1,m,o[i].y1,o[i].y2);
            if(a1>=o[i].x1&&a2<=o[i].x2)
                ans[o[i].id]=1;
        }
        sort(p+1,p+k+1,cmp4);
        sort(o+1,o+1+q,cmp2);
        build(1,1,n),cnt=1;
        for(int i=1; i<=q; ++i)
        {
            for(; cnt<=k&&p[cnt].y<=o[i].y2; ++cnt)
                update(1,1,n,p[cnt].x,p[cnt].y);
            int a1=querymin(1,1,n,o[i].x1,o[i].x2);
            int a2=querymax(1,1,n,o[i].x1,o[i].x2);
            if(a1>=o[i].y1&&a2<=o[i].y2)
                ans[o[i].id]=1;
        }
        for(int i=1; i<=q; ++i)
            if(ans[i])printf("YES
    ");
            else printf("NO
    ");
        return 0;
    }
    View Code
  • 相关阅读:
    【视频开发】图像清晰度评价方法
    【视频开发】图像清晰度评价方法
    【VS开发】MFC修改Opencv namedWindow的风格
    【VS开发】MFC修改Opencv namedWindow的风格
    【ARM-Linux开发】ctrl-xxx的对应的signal含义
    【ARM-Linux开发】ctrl-xxx的对应的signal含义
    【VS开发】程序如何捕捉signal函数参数中指定的信号
    【VS开发】程序如何捕捉signal函数参数中指定的信号
    【VS开发】windows下的signal
    【VS开发】windows下的signal
  • 原文地址:https://www.cnblogs.com/shuguangzw/p/5295884.html
Copyright © 2020-2023  润新知