http://acm.hdu.edu.cn/showproblem.php?pid=6681
题意:k条射线把平面分成多少个联通块?
思路:个数=交点数+1.
求交点数的话,离散化后,树状数组维护x坐标,将上下射线的+1和-1放到对应的y坐标,左右射线查询对应区间,按这样的做法,由y小到大扫一遍。复杂度
O
(
k
∗
l
o
g
(
k
)
)
O(k*log(k))
O(k∗log(k))
#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) (x&(-x))
const int maxn=200000+100;
typedef pair<int,int> P;
int T,n,m,k;
struct line{
int x,y;
char dir;
}a[maxn];
int d[maxn];
int sum(int x)
{
int ans=0;
while(x>0)
{
ans+=d[x];
x-=lowbit(x);
}
return ans;
}
void add(int x,int c)
{
while(x<=n)
{
d[x]+=c;
x+=lowbit(x);
}
}
vector<int> vx,vy;
vector<P> t[maxn],ask[maxn];
int main()
{
// freopen("in.txt","r",stdin);
cin>>T;
while(T--)
{
cin>>n>>m>>k;
vx.clear();
vy.clear();
for(int i=1;i<=k;i++)scanf("%d%d %c",&a[i].x,&a[i].y,&a[i].dir),vx.push_back(a[i].x),vy.push_back(a[i].y);
sort(vx.begin(),vx.end());
sort(vy.begin(),vy.end());
vx.erase(unique(vx.begin(),vx.end()),vx.end());
vy.erase(unique(vy.begin(),vy.end()),vy.end());
n=vx.size()+1;m=vy.size()+1;
for(int i=1;i<=k;i++)a[i].x=lower_bound(vx.begin(),vx.end(),a[i].x)-vx.begin()+1,a[i].y=lower_bound(vy.begin(),vy.end(),a[i].y)-vy.begin()+1;
for(int i=0;i<=max(n,m);i++)t[i].clear(),ask[i].clear();
for(int i=1;i<=k;i++)if(a[i].dir=='U'||a[i].dir=='D')
{
int x=a[i].x,y=a[i].y,dir=a[i].dir;
if(a[i].dir=='U')
{
t[y].push_back(make_pair(x,1));
}
else
{
t[1].push_back(make_pair(x,1));
t[y+1].push_back(make_pair(x,-1));
}
}
for(int i=1;i<=k;i++)if(a[i].dir=='L'||a[i].dir=='R')
{
int x=a[i].x,y=a[i].y,dir=a[i].dir;
if(dir=='R')ask[y].push_back(make_pair(x,n-1));
else ask[y].push_back(make_pair(1,x));
}
int ans=0;
memset(d,0,sizeof(d));
for(int i=1;i<=m;i++)
{
for(int j=0;j<t[i].size();j++)
{
if(t[i][j].first<=0)continue;
add(t[i][j].first,t[i][j].second);
}
for(int j=0;j<ask[i].size();j++)
{
if(ask[i][j].first<=0)continue;
ans+=sum(ask[i][j].second)-sum(ask[i][j].first-1);
}
}
cout<<ans+1<<"\n";
}
return 0;
}