题目链接:http://jnuacm.club:8080/oj/problem_show.php?pid=1187
Time Limit: 10000ms
Memory Limit: 262154KB
64-bit integer IO format: %lld Java class name: Main
木衫同学和凌小小都是军队的指挥官,他们共同管理着一队哨兵,每个哨兵都有一个位置(x,y)。但是木衫同学和凌小小计算距离的方法不一样,木衫同学计算第i个人和第j个人的距离利用以下公式 |xi - xj| + |yi - yj|,而凌小小计算时利用以下公式sqrt( (xi-xj)^2+(yi-yj)^2 )。现在问有多少组哨兵,他们之间的距离运用两种公式计算出来的结果是一样的。
Input
第一行输入一个整数T,代表有T组数据
每组数据第一行输入n(1?≤?n?≤?200000),代表哨兵的个数。
下面的n行,每行有两个整数,代表当前哨兵的坐标,(|xi|,?|yi|?≤?10^9)。
Output
每组数据输出一行,这一行只有一个整数,即符合条件的哨兵的组数。
Sample Input
2 3 1 1 7 5 1 5 6 0 0 0 1 0 2 -1 1 0 1 1 1
Sample Output
2 11
单纯暴力当然是要超时的……其实满足|xi - xj| + |yi - yj| = sqrt( (xi-xj)^2+(yi-yj)^2 )的两个点,只能是在同一条水平线或者同一条竖直线上 所以可以把不用计算两个距离,而是通过判断是否在同一条水平线或者同一条竖直线上来判断是否满足|xi - xj| + |yi - yj| = sqrt( (xi-xj)^2+(yi-yj)^2 )
1 #include<cstdio> 2 #include<cmath> 3 #include<cstdlib> 4 long long ans; 5 int n; 6 struct type{ 7 double x,y; 8 }p[200000+5]; 9 bool check(type a,type b) 10 { 11 if(a.x == b.x || a.y == b.y) return true; 12 return false; 13 } 14 int main() 15 { 16 int t; 17 scanf("%d",&t); 18 while(t--) 19 { 20 scanf("%d",&n); 21 for(int i=1;i<=n;i++) scanf("%lf%lf",&p[i].x,&p[i].y); 22 ans=0; 23 for(int i=1;i<n;i++) 24 { 25 for(int j=i+1;j<=n;j++) 26 { 27 if(check(p[i],p[j])) ans++; 28 } 29 } 30 printf("%lld\n",ans); 31 } 32 }
这大概要耗时4秒左右。
所以可以考虑把用map把出现过的水平线(y=k的k作为key值)或者竖直线记录下来(x=k的k作为key值),然后把出现过的两个哨兵在相同的点上的情况也记录下来,
这样,每输入一个哨兵的坐标,ans+= “与他在同一条水平线上的人” + “与他在同一条竖直线上的人” - “与他在同一个坐标上的人(因为这样的人重复算了两次)”
1 #include<cstdio> 2 #include<map> 3 using namespace std; 4 typedef long long ll; 5 pair<ll,ll> now; 6 map<ll,ll> a,b; 7 map<pair<ll,ll>,ll> same; 8 int n; 9 ll ans,x,y; 10 int main() 11 { 12 int t; 13 scanf("%d",&t); 14 while(t--) 15 { 16 a.clear();b.clear();same.clear(); 17 ans=0; 18 scanf("%d",&n); 19 for(int i=1;i<=n;i++) 20 { 21 scanf("%d%d",&x,&y); 22 ans=ans+a[x]+b[y]-same[make_pair(x,y)]; 23 a[x]++; 24 b[y]++; 25 same[make_pair(x,y)]++; 26 } 27 printf("%d\n",ans); 28 } 29 }
这样耗时大概是1秒左右。
时间: 2024-10-16 14:38:16