题意
给一个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;
}