Codeforces Round #243 DIV1 D問題 - Sereja and Squares

Source

Codeforces Round #243 DIV1 D問題 (2000pt)
Problem description

問題概要

二次元平面上の異なる $N$ 点の格子点 $(X_k, Y_k),\;\;k=1,2,\ldots,N$ が与えられる.
それらの中から $4$ 点を選んで,それらを頂点とする各辺が各軸に平行な正方形を作りたい.
何通りの選び方があるかを求める問題.

解法

各 $x$ 座標について,その $x$ 座標を持つ点を列挙しておく.$y$ 座標についても同様.
各点について,その点が左下($x$ が小,$y$ が小)になる正方形を列挙していく.
その点 $(x_1, y_1)$ と同じ $x$ 座標にある点のうち $y$ 座標が大きい点 $(x_1, y_2)$ を全部調べて,
$d = y_2 - y_1$ として,$(x_1 + d, y_1)$,$(x_1+d, y_1+d)$ にも点があるかどうかを調べる.
点があるかどうかは,ハッシュに入れておくか,点を列挙した時にソートしておいて2分探索を使う.
ただし,これでは,全部の点の $x$ 座標が等しい時がワーストケースで $O(N^2)$ になってしまう.
そこで,各点について,もし,その点と同じ $x$ 座標を持つ点の数より,その点と同じ $y$ 座標を持つ点の数の方が少ないなら,同様のことを $x$ と $y$ を入れ替えて行う.
すると,おそらくワーストケースでも $O(N^{1.5})$ になる.

C++のスパゲッティなコード(2分探索)

#include<cstdio>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<algorithm>
#include<string>
#include<utility>
#include<iostream>
#include<cmath>
#include<ctime>
#include<cassert>
#include<cstring>
using namespace std;

#define REP(i,a,b) for(i=a;i<b;i++)
#define rep(i,n) REP(i,0,n)

#define mygc(c) (c)=_getchar_nolock()
#define mypc(c) _putchar_nolock(c)

void reader(int *x){int k,m=0;*x=0;for(;;){mygc(k);if(k=='-'){m=1;break;}if('0'<=k&&k<='9'){*x=k-'0';break;}}for(;;){mygc(k);if(k<'0'||k>'9')break;*x=(*x)*10+k-'0';}if(m)(*x)=-(*x);}
void writer(int x, char c){int i,sz=0,m=0;char buf[10];if(x<0)m=1,x=-x;while(x)buf[sz++]=x%10,x/=10;if(!sz)buf[sz++]=0;if(m)mypc('-');while(sz--)mypc(buf[sz]+'0');mypc(c);}

int N, X[100001], Y[100001];
vector<int> xlist[100001], ylist[100001];

int main(){
  int i,j,k,l,m,d,geta, mode;
  int res = 0;
  vector<int> *lis;

  reader(&N);
  rep(i,N) reader(X+i), reader(Y+i);

  rep(i,N){
    xlist[X[i]].push_back( Y[i] );
    ylist[Y[i]].push_back( X[i] );
  }
  rep(i,100001){
    sort(xlist[i].begin(), xlist[i].end());
    sort(ylist[i].begin(), ylist[i].end());
  }

  rep(i,N){
    if(xlist[X[i]].size() < ylist[Y[i]].size()) lis = &xlist[X[i]], geta = Y[i], mode = 0;
    else                                        lis = &ylist[Y[i]], geta = X[i], mode = 1;

    rep(k,lis->size()){
      d = (*lis)[k] - geta;
      if(d<=0) continue;

      if(mode!=0 && !binary_search( xlist[X[i]].begin(), xlist[X[i]].end(), Y[i]+d)) continue;
      if(mode!=1 && !binary_search( xlist[X[i]+d].begin(), xlist[X[i]+d].end(), Y[i])) continue;
      if(!binary_search( xlist[X[i]+d].begin(), xlist[X[i]+d].end(), Y[i]+d)) continue;
      res++;
    }
  }

  writer(res, '\n');

  return 0;
}

C++のスパゲッティなコード(ハッシュ)

#include<bits/stdc++.h>
using namespace std;

#define REP(i,a,b) for(i=a;i<b;i++)
#define rep(i,n) REP(i,0,n)

#define READER_BUF_SIZE 1048576
#define WRITER_BUF_SIZE 1048576
int reader_pt=READER_BUF_SIZE,reader_last;char reader_buf[READER_BUF_SIZE];
int writer_pt=0;char writer_buf[WRITER_BUF_SIZE];
#define mygc(c) {if(reader_pt==READER_BUF_SIZE)reader_pt=0,reader_last=fread(reader_buf,sizeof(char),READER_BUF_SIZE,stdin);(c)=reader_buf[reader_pt++];}
#define mypc(c) {if(writer_pt==WRITER_BUF_SIZE)writer_pt=0,fwrite(writer_buf,sizeof(char),WRITER_BUF_SIZE,stdout);writer_buf[writer_pt++]=(c);}
#define myed {fwrite(writer_buf,sizeof(char),writer_pt,stdout);writer_pt=0;}

void reader(int *x){int k,m=0;*x=0;for(;;){mygc(k);if(k=='-'){m=1;break;}if('0'<=k&&k<='9'){*x=k-'0';break;}}for(;;){mygc(k);if(k<'0'||k>'9')break;*x=(*x)*10+k-'0';}if(m)(*x)=-(*x);}
void writer(int x, char c){int i,sz=0,m=0;char buf[10];if(x<0)m=1,x=-x;while(x)buf[sz++]=x%10,x/=10;if(!sz)buf[sz++]=0;if(m)mypc('-');while(sz--)mypc(buf[sz]+'0');mypc(c);}

#define ll long long
#define ull unsigned ll

template<class T>
struct ullHash{
  ull *key; T *val; unsigned memory, size, mask;

  void clear(){memset(val,0,size*sizeof(T));}
  void clear(int sz){size=1;while(size<sz)size*=2;mask=size-1;clear();}
  void init(int mem, int sz){memory=mem;size=1;while(size<sz)size*=2;mask=size-1;if(memory<size)memory=size;key=(ull*)malloc(memory*sizeof(ull));val=(T*)malloc(memory*sizeof(T));if(size)clear();}
  int function(ull a){return (a*97531)&mask;}
  T get(ull a){int i=function(a);for(;key[i]!=a&&val[i]!=0;)i=(i+1)&mask;if(key[i]!=a) return 0;return val[i];}
  void set(ull a, T v){int i=function(a);for(;key[i]!=a&&val[i]!=0;)i=(i+1)&mask;key[i]=a;val[i]=v;}
  T increase(ull a, T v = 1){int i=function(a);for(;key[i]!=a&&val[i]!=0;)i=(i+1)&mask;key[i]=a;return val[i]+=v;}
};

int N, X[100001], Y[100001];
vector<int> xlist[100001], ylist[100001];

int main(){
  int i,j,k,l,m,d,geta, mode;
  int res = 0;
  ullHash<ll> hash;
  ull hs;
  vector<int> *lis;

  reader(&N);
  rep(i,N) reader(X+i), reader(Y+i);

  hash.init(0, 150000);

  rep(i,N){
    xlist[X[i]].push_back( Y[i] );
    ylist[Y[i]].push_back( X[i] );
    hash.increase( X[i] * 200000LL + Y[i] );
  }

  rep(i,N){
    if(xlist[X[i]].size() < ylist[Y[i]].size()) lis = &xlist[X[i]], geta = Y[i], mode = 0;
    else                                        lis = &ylist[Y[i]], geta = X[i], mode = 1;

    rep(k,lis->size()){
      d = (*lis)[k] - geta;
      if(d<=0) continue;

      if(mode!=0 && !hash.get( (X[i]  ) * 200000LL + (Y[i]+d)) ) continue;
      if(mode!=1 && !hash.get( (X[i]+d) * 200000LL + (Y[i]  )) ) continue;
      if(           !hash.get( (X[i]+d) * 200000LL + (Y[i]+d)) ) continue;
      res++;
    }
  }

  writer(res, '\n');

  myed;
  return 0;
}

Current time: 2017年07月23日15時44分55秒
Last modified: 2014年05月03日17時25分43秒 (by laycrs)
Tags: Competitive_Programming Codeforces CF243 CF_Div1_D
トップページに戻る

Logged in as: unknown user (not login)

ログイン: