统计好元组(牛客编程巅峰赛S2第12场 - 青铜&白银&黄金)
题目描述
现在给定一个数组arr,和a,b两个数字,你要做的就是找到(i,j,k)。且满足
1. 0 <= i < j < k < arr.size()
2. |arr[i] - arr[j]| <= a
3. |arr[j] - arr[k]| <= b
统计满足条件的个数并返回(最后结果可能很大,请取1000000007的余数)。
示例
输入
[7,1,8,9,0],3,3
返回值
1
说明
只有(7,8,9)符合要求
备注
arr.size() <= 5000
其余变量均<=1e9
思路&&感想
挺简单的乘法定理,但是一开始思路没换过来
一开始以第一个数为切入点想了个O(n^3)模拟,TLE了
最后看题解要转变一下切入点,以一组数中的第二个数为切入点,左边符合条件的为k有x种情况,右边符合条件的为i有y种情况
这样最后的答案就为x*y
赛后偷看了队内大佬wlx的代码又发现了新思路
以第一个数为切入点,枚举到arr.size()-3,把每一组的第一个数都遍历一遍
在每个i里边从他后边一个元素开始枚举到arr.size()-2,每一种符合情况的j都在相应的数组中++
之后再从第二个数开始枚举到arr.size()-2,把每一组的第二个数都遍历一遍
在从其中后边一个元素枚举到arr.size()-1,只要符合条件就在计数器里边++
AC代码
思路一
class Solution { public: /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * @param arr int整型vector * @param a int整型 * @param b int整型 * @return int整型 */ int countTriplets(vector<int>& arr, int a, int b) { long long ans=0; int n=arr.size(); for(int i=0;i<n;i++) { long long x=0,y=0; for(int j=i+1;j<n;j++) { if(abs(arr[i]-arr[j])<=b) x++; } for(int j=i-1;j>=0;j--) { if(abs(arr[i]-arr[j])<=a) y++; } ans+=x*y; } return (int)(ans%1000000007); } };
思路二
class Solution { public: /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * @param arr int整型vector * @param a int整型 * @param b int整型 * @return int整型 */ int countTriplets(vector<int>& arr, int a, int b) { int x[5010]={0}; long long ans=0; for(int i=0;i<=arr.size()-3;i++) { for(int j=i+1;j<=arr.size()-2;j++) { if(abs(arr[i]-arr[j])<=a) x[j]++; } } for(int i=1;i<=arr.size()-2;i++) { int sum=0; for(int j=i+1;j<=arr.size()-1;j++) { if(abs(arr[i]-arr[j])<=b) sum++; } ans+=sum*x[i]; } return (int)(ans%1000000007); } };