zoukankan      html  css  js  c++  java
  • HDU6681 Rikka with Cake

    题意

    给一个n*m的矩形,n,m 1e9。给k(1e5)个点坐标(x,y),每个点可向上下左右发出射线,问将矩形分成几份。
    题目连接

    思路

    观察发现分成的块数等于交点数加一。离散化上下分别考虑,对于下垂下来的线按照下垂点从下向上插入树状数组,同时从下向上查询水平射线,对于向左的射线,查询小于等于其发出点x坐标的下垂线有几个,对于向右的射线,查询大于等于其发出点x坐标的下垂线有几个。对于向上的线同理。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int maxn = 100000+10;
    
    struct line
    {
        int x,y,o;
    };
    
    struct node
    {
        int p,v;
    };
    
    int n,m,k,nn,mm;
    char s[10];
    line a[maxn];
    int b[maxn],c[maxn],u[maxn],d[maxn],l[maxn],r[maxn];
    node tmp[maxn];
    int t[maxn];
    
    int lowbit(int x)
    {
        return x&(-x);
    }
    
    void add(int x)
    {
        while (x<=nn)
        {
            t[x]++;
            x+=lowbit(x);
        }
    }
    
    int ask(int x)
    {
        int ans=0;
        while (x>0)
        {
            ans+=t[x];
            x-=lowbit(x);
        }
        return ans;
    }
    
    bool cmp(node a,node b)
    {
        return a.v<b.v;
    }
    
    int main()
    {
        int T;
        scanf("%d",&T);
        while (T--)
        {
            scanf("%d%d%d",&n,&m,&k);
            for (int i=1;i<=k;i++)
            {
                scanf("%d%d",&a[i].x,&a[i].y);
                scanf("%s",s);
                if (s[0]=='U') a[i].o=1; else
                if (s[0]=='D') a[i].o=2; else
                if (s[0]=='L') a[i].o=3; else
                if (s[0]=='R') a[i].o=4;
                b[i]=a[i].x;
                c[i]=a[i].y;
            }
            nn=k;
            b[++nn]=0; b[++nn]=n;
            mm=k;
            c[++mm]=0; c[++mm]=m;
            sort(b+1,b+nn+1);
            sort(c+1,c+mm+1);
            nn=unique(b+1,b+nn+1)-b-1;
            mm=unique(c+1,c+mm+1)-c-1;
            for (int i=1;i<=k;i++)
            {
                a[i].x=lower_bound(b+1,b+nn+1,a[i].x)-b;
                a[i].y=lower_bound(c+1,c+mm+1,a[i].y)-c;
            }
            for (int i=1;i<=nn;i++) u[i]=mm,d[i]=1;
            for (int i=1;i<=mm;i++) l[i]=1,r[i]=nn;
            for (int i=1;i<=k;i++)
            {
                if (a[i].o==1) u[a[i].x]=min(u[a[i].x],a[i].y); else
                if (a[i].o==2) d[a[i].x]=max(d[a[i].x],a[i].y); else
                if (a[i].o==3) l[a[i].y]=max(l[a[i].y],a[i].x); else
                if (a[i].o==4) r[a[i].y]=min(r[a[i].y],a[i].x);
            }
            for (int i=1;i<=nn;i++)
            {
                if (u[i]<=d[i]) u[i]=1,d[i]=1;
            }
            for (int i=1;i<=mm;i++)
            {
                if (l[i]>=r[i]) l[i]=nn,r[i]=nn;
            }
    
            LL ans=1;
    
            for (int i=1;i<=nn;i++) tmp[i].p=i,tmp[i].v=u[i];
            sort(tmp+1,tmp+nn+1,cmp);
            int cur=1;
            memset(t,0,sizeof(t));
            for (int i=1;i<mm;i++)
            {
                while (cur<=nn&&tmp[cur].v<=i)
                {
                    add(tmp[cur].p);
                    cur++;
                }
                ans+=ask(l[i]);
                ans+=ask(nn)-ask(r[i]-1);
            }
    
            for (int i=1;i<=nn;i++) tmp[i].p=i,tmp[i].v=d[i];
            sort(tmp+1,tmp+nn+1,cmp);
            cur=nn;
            memset(t,0,sizeof(t));
            for (int i=mm;i>1;i--)
            {
                while (cur>=1&&tmp[cur].v>=i)
                {
                    add(tmp[cur].p);
                    cur--;
                }
                ans+=ask(l[i]);
                ans+=ask(nn)-ask(r[i]-1);
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    /etc/sysctl.conf 控制内核相关配置文件
    python 并发编程 非阻塞IO模型
    python 并发编程 多路复用IO模型
    python 并发编程 异步IO模型
    python 并发编程 阻塞IO模型
    python 并发编程 基于gevent模块 协程池 实现并发的套接字通信
    python 并发编程 基于gevent模块实现并发的套接字通信
    python 并发编程 io模型 目录
    python 并发编程 socket 服务端 客户端 阻塞io行为
    python 并发编程 IO模型介绍
  • 原文地址:https://www.cnblogs.com/zhanggengchen/p/11381818.html
Copyright © 2011-2022 走看看