【題解】[USACO20FEB]Equilateral Triangles P
阿新 • • 發佈:2021-06-10
基礎數數題。
曼哈頓距離不方便數點,比較套路的轉化為切比雪夫距離。
那麼現在要數三元組 \((i,j,k)\) 個數使得兩兩距離相等。
首選一下發現只用兩種情況,第一種是三個點構成等腰直角三角形,第二種是三個點構成銳角三角形使得存在一條平行於座標軸的邊,且該邊上的高和它的長度相等。
充分性也不難證明,首先如果三條邊都不與座標軸平行,那麼反證一下發現不存在這種情況。
否則一定存在一條邊與座標軸平行,畫出來如果這條邊上的高與它不相等,那麼也不滿足條件。
最後鈍角三角形顯然不滿足條件。所以只剩下上面兩種情況。
具體實現,我們記錄行字首和,和列字首和,然後列舉與座標軸平行的邊。求字首和的時間複雜度是 \(\mathcal{O}(N^2)\)
注意實現細節,比如轉化為切比雪夫距離後坐標可能為負數需要處理一下,座標值域會擴大為原來的兩倍。如果直接列舉新的值域會有 \(8\) 倍常數直接爆炸。但是轉化之後的網格會變稀疏,輕微剪枝就拿到了最優解(doge
#include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) #define pre(i,a,b) for(int i=a;i>=b;i--) #define N 1005 using namespace std; int n,a[N][N],u[N][N],v[N][N];char s[N][N]; int main(){ scanf("%d",&n); rep(i,1,n)scanf("%s",s[i]+1); rep(i,1,n)rep(j,1,n)if(s[i][j]=='*')a[i+j][i-j+n]=1; int m=2*n; rep(i,1,m)rep(j,1,m)u[i][j]=u[i][j-1]+a[i][j]; rep(j,1,m)rep(i,1,m)v[i][j]=v[i-1][j]+a[i][j]; int ans=0; rep(k,1,m)rep(i,1,m)if(a[i][k])rep(j,i+1,m)if(a[j][k]){ if(k>j-i)ans+=v[j][k-j+i]-v[i-1][k-j+i]; if(m-k>=j-i)ans+=v[j][k+j-i]-v[i-1][k+j-i]; } rep(k,1,m)rep(i,1,m)if(a[k][i])rep(j,i+2,m)if(a[k][j]){ if(k>j-i)ans+=u[k-j+i][j-1]-u[k-j+i][i]; if(m-k>=j-i)ans+=u[k+j-i][j-1]-u[k+j-i][i]; } printf("%d\n",ans); return 0; }