思路:
一个人对该值的贡献与他的朝向和位置有关。
我们发现每个人都是独立的,也就是我想看到别人只取决于我的位置,而不取决于别人的方向。因此我们考虑每个人改变方向的会增加的贡献。
假设共有n个人,对第i个人来说,朝左有i-1个人,朝右有n-i个人。
朝左->朝右:n-i-(i-1)=n+1-2i;
朝右->朝左:i-1-(n-i)=2i-n-1;
所以!!!
我们可以计算出每一个人转头之后贡献值的变化,我们可以将这些数存在vector中,将这些变化从大到小排列,当需要改变k个人的方向时,我们只需要在原来的队伍值的基础+前k个即可。
代码:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
const int N=2e5+10;
int t;
int main()
{
cin>>t;
while(t--)
{
int n;
cin>>n;
char s[N];
scanf("%s",s+1);
vector<int> v;//v代表改变后的贡献变化值增加
ll ans=0;
for(int i=1;i<=n;i++)
{
if(s[i]=='L')
{
if(n-i>i-1) v.push_back(n-i-(i-1));//朝右看的人多于朝左看的人
ans+=i-1;//朝左看的人更多
}
else
{
if(i-1>n-i) v.push_back(i-1-(n-i));//朝左看的人更多
ans+=n-i;
}
}
sort(v.begin(),v.end(),[](int x,int y)
{return x>y;});
for(int i=1;i<=n;i++)//k=i,代表最多可改变k个数的方向
{
if(i<=v.size()) ans+=v[i-1];//如果可改变的数量足够,答案就加上v
cout<<ans<<" ";
}
cout<<endl;
}
return 0;
}