题意:
给你几个圆,几个点,问你点与点之间隔了多少个圆。
POINT:
1.暴力: 500ms
记录下每个点在每个圆的外面还是里面, 点与点不一样就ans++。
2.状态压缩:180ms
差不多,只是用异或来寻求答案。
用bitset来存下1000位的01串。
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <algorithm>
#include <bitset>
using namespace std;
#define LL long long
const LL maxn = 2e3 + 10;
LL n,m,k,x[maxn],y[maxn],z;
struct node{
LL r,x,y;
}C[maxn];
bitset<1010> a[1111];
int main()
{
scanf("%lld%lld%lld",&n,&m,&k);
for(LL i=1;i<=n;i++){
scanf("%lld%lld",&x[i],&y[i]);
a[i].reset();
}
for(LL i=1;i<=m;i++){
scanf("%lld%lld%lld",&C[i].r,&C[i].x,&C[i].y);
}
for(LL i=1;i<=n;i++){
for(LL j=1;j<=m;j++){
LL len = (x[i]-C[j].x)*(x[i]-C[j].x)+(y[i]-C[j].y)*(y[i]-C[j].y);
if(len<=C[j].r*C[j].r){
a[i][j]=1;
}else{
a[i][j]=0;
}
}
}
while(k--)
{
LL q,w;
scanf("%lld %lld",&q,&w);
printf("%lld\n",(LL)(a[q]^a[w]).count());
}
return 0;
}
3.建图+lca:250ms。
的确是250的做法。把每个圆和他的父圆连一条边。父圆(最近的包含他的圆)。这样就建了一颗树,根为无限大的圆。
然后每个点属于哪个圆。跑lca。
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <algorithm>
#include <queue>
using namespace std;
#define LL long long
const LL maxn = 2e3 + 10;
LL n,m,k,x[maxn],y[maxn],z;
struct node{
LL r,x,y;
}C[maxn];
bool cmp(node a,node b){
return a.r<b.r;
}
LL check(LL i,LL j){
LL len = (C[i].x-C[j].x)*(C[i].x-C[j].x) + (C[i].y-C[j].y)*(C[i].y-C[j].y);
if(len<=C[j].r*C[j].r) return 1;
return 0;
}
const LL N = 1e6 + 10;
LL v[N],ft[N],nt[N],sz = 0;
LL dian[N];
LL fa[N][20];
LL vis[N];
LL d[N];
void dfs(LL u)
{
vis[u]=1;
for(LL i=ft[u];i;i=nt[i]){
LL to = v[i];
if(vis[to]) continue;
d[to]=d[u]+1;
dfs(to);
fa[to][0]=u;
}
}
void lcainit()
{
for(LL j=1;j<=(LL)log2(m+1);j++){
for(LL i=0;i<=m;i++){
fa[i][j]=fa[fa[i][j-1]][j-1];
}
}
}
LL query(LL a,LL b)
{
if(d[a]<d[b]) swap(a,b);
LL xx=a;
LL yy=b;
LL dis=d[a]-d[b];
for(LL i=0;i<=(LL)log2(m+1);i++){
if((1<<i)&dis){
a=fa[a][i];
}
}
if(a==b){
return dis;
}
for(LL i=(LL)log2(m+1);i>=0;i--){
if(fa[a][i]!=fa[b][i]){
a=fa[a][i];
b=fa[b][i];
}
}
a=fa[a][0];
return d[xx]-d[a]+d[yy]-d[a];
}
int main()
{
scanf("%lld%lld%lld",&n,&m,&k);
for(LL i=0;i<n;i++){
scanf("%lld%lld",&x[i],&y[i]);
}
for(LL i=0;i<m;i++){
scanf("%lld%lld%lld",&C[i].r,&C[i].x,&C[i].y);
}
sort(C,C+m,cmp);
for(LL i=0;i<m;i++){
LL f = 1;
for(LL j=i+1;j<m;j++){
if(check(i,j)){
v[++sz] = j; nt[sz] = ft[i]; ft[i] = sz;
v[++sz] = i; nt[sz] = ft[j]; ft[j] = sz;
f = 0;
break;
}
}
if(f){
v[++sz] = m; nt[sz] = ft[i]; ft[i] = sz;
v[++sz] = i; nt[sz] = ft[m]; ft[m] = sz;
}
}
for(LL i=0;i<n;i++){
LL f = 1;
for(LL j=0;j<m;j++){
LL len = (x[i]-C[j].x)*(x[i]-C[j].x)+(y[i]-C[j].y)*(y[i]-C[j].y);
if(len<=C[j].r*C[j].r){
dian[i] = j;
f = 0;
break;
}
}
if(f) dian[i] = m;
}
/* cout<<endl;cout<<endl;cout<<endl;
for(int i=0;i<n;i++) cout<<dian[i]<<" ";
cout<<endl;
for(int i=0;i<=m;i++){
cout<<i<<" ";
for(int j=ft[i];j;j=nt[j]){
cout<<v[j]<<" ";
}
cout<<endl;
}
cout<<endl;cout<<endl;cout<<endl;*/
dfs(m);
lcainit();
while(k--)
{
LL a,b;
scanf("%lld %lld",&a,&b);
printf("%lld\n",query(dian[a-1],dian[b-1]));
}
return 0;
}
ps:
cf很强大,一秒可以跑好几亿