【codeforces 752D】Santa Claus and a Palindrome

time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
Santa Claus likes palindromes very much. There was his birthday recently. k of his friends came to him to congratulate him, and each of them presented to him a string si having the same length n. We denote the beauty of the i-th string by ai. It can happen that ai is negative — that means that Santa doesn’t find this string beautiful at all.

Santa Claus is crazy about palindromes. He is thinking about the following question: what is the maximum possible total beauty of a palindrome which can be obtained by concatenating some (possibly all) of the strings he has? Each present can be used at most once. Note that all strings have the same length n.

Recall that a palindrome is a string that doesn’t change after one reverses it.

Since the empty string is a palindrome too, the answer can’t be negative. Even if all ai’s are negative, Santa can obtain the empty string.

Input
The first line contains two positive integers k and n divided by space and denoting the number of Santa friends and the length of every string they’ve presented, respectively (1 ≤ k, n ≤ 100 000; n·k  ≤ 100 000).

k lines follow. The i-th of them contains the string si and its beauty ai ( - 10 000 ≤ ai ≤ 10 000). The string consists of n lowercase English letters, and its beauty is integer. Some of strings may coincide. Also, equal strings can have different beauties.

Output
In the only line print the required maximum possible beauty.

Examples
input
7 3
abb 2
aaa -3
bba -1
zyz -4
abb 5
aaa 7
xyx 4
output
12
input
3 1
a 1
a 2
a 3
output
6
input
2 5
abcde 10000
abcde 10000
output
0
Note
In the first example Santa can obtain abbaaaxyxaaabba by concatenating strings 5, 2, 7, 6 and 3 (in this order).

【题目链接】:http://codeforces.com/contest/752/problem/D

【题解】

因为是由一个个字符串拼接起来的;
所以如果s本身不是回文串的话;
必须有一个s的倒序字符串和其对应;
这样才能放在左边和右边形成回文串的一个部分;
所以用一个map存同一个字符串有哪些数值ai;
并把这些ai按照降序排;
如果某个字符串s本身不是回文串->则只能放在最后整个回文串的左边和右边;
所以要看一下s倒序后的字符串存不存在;如果不存在;则这个字符串最后不能加入到最后的回文串中;
否则
可以加入;
加入的话,s和s的倒序的都取ai数值大的选就好(贪心);
累加答案一下就可以了;
s本身是回文串的有些特殊;
需要考虑这个s是放在中间的位置还是放在左边和右边;
左边和右边的直接每两个选一组就好;
中间的那个需要在剩余的字符串中选;
或者每两个中出现了有一个为负的;但是它们的和仍旧大于0
则我们可以尝试只选那个正的(把它放在最中间)。以让其更优;
所以原则就是先找左边和右边配对的;
然后看看能不能找到一个放在最中间;

【完整代码】

#include <bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define rei(x) scanf("%d",&x)
#define rel(x) scanf("%I64d",&x)

typedef pair<int,int> pii;
typedef pair<LL,LL> pll;

const int MAXN = 1e5+100;
const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
const double pi = acos(-1.0);

int k,n,extra;
LL ans = 0,ans1;
map <string,vector <int> > dic;

bool cmp(int a,int b)
{
    return a>b;
}

int main()
{
    //freopen("F:\\rush.txt","r",stdin);
    rei(k);rei(n);
    string s;int x;
    rep1(i,1,k)
    {
        cin >> s >> x;
        dic[s].pb(x);
    }
    for (auto &p :dic)
    {
        auto& x = p.fi;
        auto& v = p.se;
        sort(v.begin(),v.end(),cmp);
        int len = v.size();
        auto re = x;
        reverse(re.begin(),re.end());
        if (re==x)
        {
            int i;
            for (i = 0;i+1<=len-1 && v[i]+v[i+1]>=0;i+=2)
            {
                ans+=v[i]+v[i+1];
                extra = max(extra,-min(v[i],v[i+1]));
            }
            for (;i <= len-1;i++)
                extra = max(extra,v[i]);
        }
        else
        {
            if (dic[re].empty())
                continue;
            auto& vv = dic[re];
            int len2 = vv.size();
            sort(vv.begin(),vv.end(),cmp);
            len = min(len,len2);
            rep1(i,0,len-1)
                if (v[i]+vv[i]>0)
                    ans1+=(v[i]+vv[i]);
        }
    }
    cout << ans1/2+ans+extra;
    return 0;
}

转载于:https://www.cnblogs.com/AWCXV/p/7626765.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值