[阈值] SPOJ RECTANGL

来源:互联网 发布:淘宝拍卖烂尾楼 编辑:程序博客网 时间:2024/06/05 05:05

详见 一类算法复合的方法

大概就是把坐标都离散了
按照某x坐标上的点数分类
如果矩形的某边是大类 只有O(n) 直接枚举所有点按 y hash就行了
否则所有小类 把所有能构成的线段放进hash表 只有O(nn)

再一次体验了unordered_map的感人速度

#include<cstdio>#include<cstdlib>#include<algorithm>#include<vector>#include<cmath>#include<tr1/unordered_map>  #include<tr1/unordered_set>  #define pb push_backusing namespace std;using namespace std::tr1;typedef vector<int> VI;typedef long long ll;inline char nc(){  static char buf[100000],*p1=buf,*p2=buf;  return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}inline void read(int &x){  char c=nc(),b=1;  for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;  for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;}const int N=250005;int sx[N],icnt;inline int Bin(int x){  return lower_bound(sx+1,sx+icnt+1,x)-sx;}int n;int x[N],y[N];VI Y[N];int cnt[N];unordered_set<int> Set;//unordered_map<ll,int> Map;//typedef unordered_map<ll,int>::iterator IT;ll AA,AB,BB;const int M=12500005;const int P=10000007;struct HashMap{  ll k[M]; int v[M],next[M];  int head[P],inum;  int&operator[](ll x){    for (int p=head[x%P];p;p=next[p])      if (k[p]==x)    return v[p];    ++inum; k[inum]=x; v[inum]=0; next[inum]=head[x%=P]; head[x]=inum;    return v[inum];  }}Map;int main(){  freopen("t.in","r",stdin);  freopen("t.out","w",stdout);  read(n);  for (int i=1;i<=n;i++) read(x[i]),read(y[i]);  icnt=0; for (int i=1;i<=n;i++) sx[++icnt]=y[i];  sort(sx+1,sx+icnt+1); icnt=unique(sx+1,sx+icnt+1)-sx-1;  for (int i=1;i<=n;i++) y[i]=Bin(y[i]);  icnt=0; for (int i=1;i<=n;i++) sx[++icnt]=x[i];  sort(sx+1,sx+icnt+1); icnt=unique(sx+1,sx+icnt+1)-sx-1;  for (int i=1;i<=n;i++) x[i]=Bin(x[i]),cnt[x[i]]++,Y[x[i]].pb(y[i]);  for (int i=1;i<=icnt;i++) sort(Y[i].begin(),Y[i].end());  int B=sqrt(n);  for (int i=1;i<=icnt;i++)    if (cnt[i]>B){            for (int j=0;j<cnt[i];j++)    Set.insert(Y[i][j]);      for (int j=1;j<=icnt;j++){    if (i==j) continue;    if (cnt[j]>B){      int c=0;      for (int k=0;k<cnt[j];k++)        if (Set.count(Y[j][k]))          c++;      AA+=(ll)c*(c-1)/2;    }else{      int c=0;      for (int k=0;k<cnt[j];k++)        if (Set.count(Y[j][k]))          c++;      AB+=(ll)c*(c-1)/2;    }      }      Set.clear();    }  for (int i=1;i<=icnt;i++)    if (cnt[i]<=B)      for (int j=0;j<cnt[i];j++)    for (int k=j+1;k<cnt[i];k++)      Map[((ll)Y[i][j]<<32)+Y[i][k]]++;  for (int i=1;i<=Map.inum;i++)    BB+=(ll)Map.v[i]*(Map.v[i]-1)/2;  /*for (IT i=Map.begin();i!=Map.end();i++)    BB+=(ll)i->second*(i->second-1)/2;*/  printf("%lld\n",AA/2+AB+BB);  return 0;}
0 0