P7756 [COCI2012-2013#3] MALCOLM

因为只有名字长度相等的同学才能成为好朋友,所以我们就把名字长度相同的同学的排名放入同一个数组内。

vector<int>e[30];
string s;
for(int i=1;i<=n;i++)
{
	cin>>s;
	e[s.size()].push_back(i);
}

接下来对于每个长度的名字,我们分开计算,每次用双指针 i,ji,j 实现。

举个例子

假设名字长度为 22 的同学的排名为 1 3 4 51\ 3\ 4\ 5,数组长度 l2=4l_2=4,题目中的 k=2k=2

先令 i=j=0i=j=0

e2,0e_{2,0} e2,1e_{2,1} e2,2e_{2,2} e2,3e_{2,3}
11 33 44 55
i,ji,j

接下来令 jj 不断增加,直到 j==l21j==l_2-1e2,i+k<e2,j+1e_{2,i}+k<e_{2,j+1},也就是求出当前这个同学的交际圈至多能低到第几名。

e2,0e_{2,0} e2,1e_{2,1} e2,2e_{2,2} e2,3e_{2,3}
11 33 44 55
ii j{}^\curvearrowright j

此时第 ii 个同学就能找到 jij-i 名排名比自己低的好朋友,于是我们让 ans+=jians+=j-i

接下来再进行几轮这样的操作,每次完成后令 i++i++,寻找第 ii 个同学能找到的排名最低的好朋友,直到 i==l22i==l_2-2

e2,0e_{2,0} e2,1e_{2,1} e2,2e_{2,2} e2,3e_{2,3}
11 33 44 55
i,j{}^\curvearrowright i,j
e2,0e_{2,0} e2,1e_{2,1} e2,2e_{2,2} e2,3e_{2,3}
11 33 44 55
ii j{}^\curvearrowright j
e2,0e_{2,0} e2,1e_{2,1} e2,2e_{2,2} e2,3e_{2,3}
11 33 44 55
ii j{}^\curvearrowright j
e2,0e_{2,0} e2,1e_{2,1} e2,2e_{2,2} e2,3e_{2,3}
11 33 44 55
i{}^\curvearrowright i jj

把每次的 jij-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)O(\sum_{i=2}^{20}l_i)=O(n)

posted @ 2021-08-01 23:23  luckydrawbox  阅读(12)  评论(0)    收藏  举报  来源