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\n",ans);
    }
    return 0;
}
posted @ 2019-08-20 11:14  zhanggengchen  阅读(115)  评论(0)    收藏  举报