Codeforces Round #461 (Div. 2) D. Robot Vacuum Cleaner

D. Robot Vacuum Cleaner

time limit per test 1 second
memory limit per test 256 megabytes

Problem Description

Pushok the dog has been chasing Imp for a few hours already.
这里写图片描述
Fortunately, Imp knows that Pushok is afraid of a robot vacuum cleaner.

While moving, the robot generates a string t consisting of letters ‘s’ and ‘h’, that produces a lot of noise. We define noise of string t as the number of occurrences of string “sh” as a subsequence in it, in other words, the number of such pairs (i, j), that i < j and and .

The robot is off at the moment. Imp knows that it has a sequence of strings ti in its memory, and he can arbitrary change their order. When the robot is started, it generates the string t as a concatenation of these strings in the given order. The noise of the resulting string equals the noise of this concatenation.

Help Imp to find the maximum noise he can achieve by changing the order of the strings.

Input

The first line contains a single integer n (1 ≤ n ≤ 1e5) — the number of strings in robot’s memory.

Next n lines contain the strings t1, t2, …, tn, one per line. It is guaranteed that the strings are non-empty, contain only English letters ‘s’ and ‘h’ and their total length does not exceed 1e5.

Output

Print a single integer — the maxumum possible noise Imp can achieve by changing the order of the strings.

Examples

Input
4
ssh
hs
s
hhhs
Output
18

Input
2
h
s
Output
1

Note

The optimal concatenation in the first sample is ssshhshhhs.


解题心得:

  1. 就是让你将这写字符串拼接成一个,要求子序列出现sh的次数要最多,并且打印出现的次数。
  2. 一开始以为是一个dp,推了一会儿发现推不出来。其实就是一个贪心,s要尽可能的放在前面,h要尽可能的放在后面,那么如果排序后拼接,是以s数目为准还是h呢,好像都不太对,然后根据直觉写了个s和h数目的比例,按照比例排序,然后过了。感觉有点迷。其实想想确实是这样,比例反映的是s和h两个标准对整个字符串出现sh数目尽可能多的贡献,s贡献大就放在前面,h贡献大就放在后面,符合前面提出的贪心的思想。
  3. 要注意一下在计算比例的时候分母出现0的情况,还有就是题意中说的是字符串拼接之后总长度不超过1e5,不然就1s的时间总长度都1e10了还怎么写。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+100;
const long long Max = 1e11;
struct String{
    double p;
    int num_s,num_h,temp;
    friend bool operator < (const String a,const String b) {//按照s和h的比例从大到小排序
        return a.p > b.p;
    }
}st[maxn];

int n;

void init(){
    char s[maxn];
    for(int i=0;i<n;i++){
        scanf("%s",s);
        int len = strlen(s);
        int num_s,num_h,temp;
        num_s = num_h = temp = 0;
        for(int j=0;j<len;j++){
            if(s[j] == 's')
                num_s++;
            else{
                temp += num_s;//字串自身能形成多少个sh
                num_h++;
            }
        }
        double p;
        if(num_h == 0)//分母是0直接赋予最大值
            p = Max;
        else
            p = (double)num_s/(double)num_h;
        st[i].num_s = num_s;
        st[i].num_h = num_h;
        st[i].temp = temp;
        st[i].p = p;
    }
    sort(st,st+n);
}

long long get_ans(){
    long long ans = 0,num_s = 0;
    for(int i=0;i<n;i++){
        ans += st[i].temp;//自身出现的sh数目
        ans += num_s*st[i].num_h;//当前串和前面已经拼接好的串形成的sh数目
        num_s += st[i].num_s;
    }
    return ans;
}

int main(){
    scanf("%d",&n);
    init();
    long long ans = get_ans();
    printf("%lld\n",ans);
    return 0;
}

转载于:https://www.cnblogs.com/GoldenFingers/p/9107175.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值