Codeforces Round #690 (Div. 3) E1. Close Tuples (easy version) (贪心+思维)
https://codeforces.com/contest/1462/problem/E1
E1. Close Tuples (easy version)
题目大意:
给定一个长度为n的序列a,由1到n的整数组成,某些元素可能相等。
找出m=3个元素的元组的数目,使得元组中的最大数目与最小值相差不超过k=2。
输出数量。
input
4
4
1 2 4 3
4
1 1 1 1
1
1
10
5 6 1 3 2 9 8 1 2 4
output
2
4
0
15
因为每一个数字都有它自己唯一的位置编号,所以我们对它进行排序后再做运算对结果没有影响,先固定左边界,右划寻找右边界
先找到最大的那个,然后依次左边界依次右滑,以此计算个数:(固定右边界再划左边界比固定左边界画右边界计数更好,因为不用再倒回来重新计算)
3 4 5 6 7......
1 3 6 10 15...... (每次增加一个单位的长度增加的个数:1* 2/2;2* 3/2;3* 4/2;4* 5/2;5* 6/2......)
1 4 10 20 35......
这个求个数的式子肥肠重要,要记住!
ans+=(LL)(j-i)*(j-i-1)/2;
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL,LL> PII;
const LL MAXN=1e18;
const LL N=500200,M=2002;
LL a[N];
int main()
{
cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);
LL T=1;
cin>>T;
while(T--)
{
LL n;
cin>>n;
LL m=3,k=2;
for(int i=1;i<=n;i++)
cin>>a[i];
sort(a+1,a+1+n);
LL ans=0;
for(int i=1,j=1;i<=n;i++)
{
while(j<n&&a[j+1]-a[i]<=k) j++;
if(j-i>=2)
{
ans+=(LL)(j-i)*(j-i-1)/2;
// cout<<i<<" "<<j<<" "<<ans<<endl;
}
}
cout<<ans<<endl;
}
return 0;
}