因为只有名字长度相等的同学才能成为好朋友,所以我们就把名字长度相同的同学的排名放入同一个数组内。
vector<int>e[30];
string s;
for(int i=1;i<=n;i++)
{
cin>>s;
e[s.size()].push_back(i);
}
接下来对于每个长度的名字,我们分开计算,每次用双指针 i,j 实现。
举个例子
假设名字长度为 2 的同学的排名为 1 3 4 5,数组长度 l2=4,题目中的 k=2。
先令 i=j=0。
| e2,0 |
e2,1 |
e2,2 |
e2,3 |
| 1 |
3 |
4 |
5 |
| i,j |
|
|
|
接下来令 j 不断增加,直到 j==l2−1 或 e2,i+k<e2,j+1,也就是求出当前这个同学的交际圈至多能低到第几名。
| e2,0 |
e2,1 |
e2,2 |
e2,3 |
| 1 |
3 |
4 |
5 |
| i |
↷j |
|
|
此时第 i 个同学就能找到 j−i 名排名比自己低的好朋友,于是我们让 ans+=j−i。
接下来再进行几轮这样的操作,每次完成后令 i++,寻找第 i 个同学能找到的排名最低的好朋友,直到 i==l2−2。
| e2,0 |
e2,1 |
e2,2 |
e2,3 |
| 1 |
3 |
4 |
5 |
|
↷i,j |
|
|
| e2,0 |
e2,1 |
e2,2 |
e2,3 |
| 1 |
3 |
4 |
5 |
|
i |
↷j |
|
| e2,0 |
e2,1 |
e2,2 |
e2,3 |
| 1 |
3 |
4 |
5 |
|
i |
|
↷j |
| e2,0 |
e2,1 |
e2,2 |
e2,3 |
| 1 |
3 |
4 |
5 |
|
|
↷i |
j |
把每次的 j−i 累加就是答案。
#include<bits/stdc++.h>
using namespace std;
int n,k;
vector<int>e[30];
string s;
ll ans;
int main()
{
cin>>n>>k;
for(int i=1;i<=n;i++)
{
cin>>s;
e[s.size()].push_back(i);
}
for(int l=2;l<=20;l++)
if(e[l].size()>1)
{
int i=0,j=0;
while(i<e[l].size()-1)
{
while(j+1<e[l].size()&&e[l][i]+k>=e[l][j+1])
j++;
ans+=j-i;
i++;
}
}
cout<<ans<<endl;
return 0;
}
复杂度为 O(∑i=220li)=O(n)。