发布于 

CF 461 D

CF 461 D

作为D题来说是比较水的了,但是最后因为最后答案用int存不开,所以在比赛时并没有A掉。

题解

题目要求给出指定个由sh组成的字符串,怎样将这些字符串排列可以使得sh对最多。一个sh对存在当且仅当s的下标在h前。最后只需输出sh对的数目即可。

因此,我们可以发现最终的ans的求解可以分为两部分:

  1. sh在同一个字符串内时,无论字符串如何排列,其构成的sh对的数目不变,所以我们只需在读入时处理出来这些数值即可。

  2. sh不再同一个字符串内时。对于两个字符串Str1Str2,其之间产生的sh对的数目为$Str1.s Str2.h \(或\) Str2.s Str1.h \((`.s`为字符串中`s`的数目,`.h`亦然)。这样,我们可以通过比较这两个数值的大小来确定`Str1`与`Str2`的顺序。而对于更多数目的字符串,同理。所以我们只需要对所有的字符串按照\) $的降序排列即可。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <cstdio>
#include <iostream>
#include <algorithm>

char s[100100];

struct Cnt
{
trueint s; //分别代表该字符串中有多少个s和h
trueint h;

trueconst bool operator < (const Cnt& tmp)const{
truetruereturn (long long)s*tmp.h > (long long)tmp.s*h;
true}
}cnt[100100];

int main()
{
truelong long ans = 0;

trueint n;
truescanf("%d",&n);
truefor (int j = 0; j<n; j++)
true{
truetruestd::cin >> s;

truetruecnt[j].s = 0; //初始化为0
truetruecnt[j].h = 0;

truetruefor (int i = 0; s[i]!='\0'; i++)
truetruetrueif (s[i]=='h')
truetruetrue{
truetruetruetrueans += cnt[j].s; //h会与该字符串中前面的所有s配对,所以出现h是答案会加cnt[j].s
truetruetruetruecnt[j].h++;
truetruetrue}else if (s[i]=='s'){
truetruetruetruecnt[j].s++;
truetruetrue}
true}

truestd::sort(cnt,cnt+n); //排序,令s/h比较大的排在前面

truelong long t = 0;
truefor (int i = 0; i<n; i++)
true{
truetrueans += t*cnt[i].h;
truetruet += cnt[i].s;

true}

truestd::cout << ans;
}

本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

本站由 [@Songer](https://blog.songer.xyz/) 创建,使用 Stellar 作为主题。