【NOIP模拟题】【hash表】【暴力求解】2016.11.16 第三题 LGTB 与正方形 题解

LGTB 与正方形

LGTB 最近迷上了正方形,现在他有n 个在二维平面上的点,请你告诉他在这些点中选4 个点能组成四条边都平行于坐标轴的正方形的方案数有多少

输入
输入第一行包含一个整数n,代表点的数量
接下来n 行每行包含两个整数xi, yi,代表点的坐标
对于10% 的数据,1<=n <=50
对于30% 的数据,1<=n<=1000
对于100% 的数据,1<=n<=10^5,0<=xi, yi <=10^5
数据保证没有两点在同一位置

输出
输出包含一个整数代表方案数

样例
样例输入 样例输出
5 1
0 0
0 2
2 0
2 2
1 1

样例输入 样例输出
9 5
0 0
1 1
2 2
0 1
1 0
0 2
2 0
1 2
2 1

好迷哦,这道题,做不来。然而某巨巨还写了一个我看不懂的程序。GG。
那么就大概de说一下。
将原坐标通过x分类,设每个分类为P[x]。如果P[x]中数的个数小于sqrt(n),直接暴力枚举里面元素。(x相同,判断y获取正方形)另外的P[x]暴力枚举这些集合,判断其中那些是y相等的。对于第一类小于sqrt(n)的点的集合,每个集合里面最多sqrt(n)个元素,所以该时间复杂度为O(n sqrt(n))
以上,来自另外一个巨巨。

附STD代码:

#include <set>
#include <cmath>
#include <stack>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <numeric>
#include <vector>
#include <ctime>
#include <queue>
#include <list>
#include <map>
#define pi acos(-1.0)
#define INF 0x3f3f3f3f
#define clr(x)  memset(x,0,sizeof(x));
#define clrto(x,siz,y)  for(int xx=0;xx<=siz;xx++)  x[xx]=y;
#define clrset(x,siz)  for(int xx=0;xx<=siz;xx++)  x[xx]=xx;
#define clr_1(x) memset(x,-1,sizeof(x));
#define clrmax(x) memset(x,0x3f,sizeof(x));
#define clrvec(x,siz) for(int xx=0;xx<=siz;xx++)  x[xx].clear();
#define fop2   freopen(".in","r",stdin); //freopen(".out","w",stdout);
#define fop   freopen("in.txt","r",stdin);//freopen("out.txt","w",stdout);
#define myprogram By_135678942570
#define clrcpy(x,siz,y)  for(int xx=0;xx<siz;xx++)  x[xx]=y[xx];
#define pb push_back
using namespace std;
struct point
{
    int x,y;
}P[100011];
int SIZ=400;
struct hash_map
{
    const static int mod=100007;
    int head[mod];
    struct hash_tables
    {
        long long key;
        int val;
        int next;
    }ele[100007];
    int N;
    int getHash(long long x)
    {
        return x%mod;
    }
    void init()
    {
        memset(head,255,sizeof(head));
        N=0;
    }
    int fint(long long x)
    {
        for(int i=head[getHash(x)];i!=-1;i=ele[i].next)
            if(ele[i].key==x)
                return i;
        return -1;
    }
    void insert(long long x)
    {
        int tmp=getHash(x);
        ele[N].key=x;
        ele[N].val=0;
        ele[N].next=head[tmp];
        head[tmp]=N++;
    }
    int& operator [](long long x)
    {
        int tmp=fint(x);
        if(tmp==-1)
        {
            insert(x);
            return ele[N-1].val;
        }
        else return ele[tmp].val;
    }
}HT;
vector<int>row[100111];
vector<int>GREAT;
vector<int>LESS;
int main()
{
    // fop;
    freopen("square.in", "r", stdin);
    freopen("square.out", "w", stdout);
    HT.init();
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%d%d",&P[i].x,&P[i].y);
        row[P[i].x].pb(P[i].y);
        HT.insert(P[i].x*1000003ll+P[i].y);
    }
    for(int i=0;i<=100000;i++)
        if(row[i].size()>=SIZ)
            GREAT.pb(i);
        else if(row[i].size()>0)
            LESS.pb(i);
    int res=0;
    for(int i=0;i<LESS.size();i++)
    {
        int rowid=LESS[i];
        for(int j=0;j<row[rowid].size();j++)
            for(int k=j+1;k<row[rowid].size();k++)
            {
                int x1=rowid;
                int y1=row[rowid][j],y2=row[rowid][k];
                int x2=x1+abs(y1-y2);
                int x22=x1-abs(y1-y2);
                int f1=HT.fint(x2*1000003ll+y1);
                int f2=HT.fint(x2*1000003ll+y2);
                if(f1!=-1&&f2!=-1)
                {
                    res++;
                }
                if(x22>=0&&row[x22].size()>=SIZ)
                {
                    f1=HT.fint(x22*1000003ll+y1);
                    f2=HT.fint(x22*1000003ll+y2);
                    if(f1!=-1&&f2!=-1)
                        res++;
                }
            }
    }
    for(int i=0;i<GREAT.size();i++)
        sort(row[GREAT[i]].begin(),row[GREAT[i]].end());
    for(int i=0;i<GREAT.size();i++)
        for(int j=i+1;j<GREAT.size();j++)
        {
            int x1=GREAT[i];
            int x2=GREAT[j];
            int len=abs(x1-x2);
            int ii=0,jj=0;
            while(ii<row[x1].size()&&jj<row[x2].size())
            {
                if(row[x1][ii]==row[x2][jj])
                {
                    int f1=HT.fint(x1*1000003ll+row[x1][ii]+len);
                    int f2=HT.fint(x2*1000003ll+row[x2][jj]+len);
                    if(f1!=-1&&f2!=-1)
                        res++;
                    ii++,jj++;
                }
                else if(row[x1][ii]>row[x2][jj])
                    jj++;
                else ii++;
            }
        }
    printf("%d\n",res);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值