• 【Codeforces752D】Santa Claus and a Palindrome [STL]


    Santa Claus and a Palindrome

    Time Limit: 20 Sec  Memory Limit: 512 MB

    Description

      有k个串,串长都是n,每个串有一个ai的贡献。
      选出若干个串,若它们可以通过任意组合,形成一个回文串,则可以获得它们的贡献之和。
      求最大贡献。

    Input

      第一行两个整数k,n。
      之后k行,每行分别是一个串si,与贡献ai。

    Output

      一个整数表示答案。

    Sample Input

      7 3
      abb 2
      aaa -3
      bba -1
      zyz -4
      abb 5
      aaa 7
      xyx 4

    Sample Output

      12

    HINT

      1 ≤ k, n ≤ 100000;  n·k  ≤ 100000;  -10000 ≤ ai ≤ 10000

    Solution

      首先,我们先考虑选了偶数个串的情况。显然是每两个互相颠倒的串匹配,尽量选大的值。

      但是现在可能选奇数个串,就是考虑把一个回文串放在中间,显然有两种情况:

        1. 匹配完还剩若干串,在剩下的串单独选了个回文串,显然加上最大的贡献即可;

        2. 把之前某些回文串两两匹配的给拆开改成只选较大的那一个,因为只选一个串可能贡献更大,A > (A + B)

      具体实现我们可以用一个Map指向一个vector,vector存下价值Map[s]=id表示s这个串用第id个vector记录信息

    Code

     1 #include<iostream>
     2 #include<string>
     3 #include<algorithm>
     4 #include<cstdio>
     5 #include<cstring>
     6 #include<cstdlib>
     7 #include<cmath>
     8 #include<map>
     9 #include<vector>
    10 using namespace std;
    11 typedef long long s64;
    12 
    13 const int ONE = 100005;
    14 const int MOD = 1e9 + 7;
    15 const int Base = 10005;
    16 
    17 int k, n;
    18 
    19 int total = 0;
    20 map <string, int> id;
    21 vector <int> A[ONE];
    22 
    23 int Ans;
    24 
    25 char s[ONE];
    26 struct power
    27 {
    28         string s;
    29         int val;
    30 }a[ONE];
    31 bool cmp(const power &a, const power &b) {return a.val > b.val;}
    32 
    33 
    34 int get()
    35 {
    36         int res=1,Q=1;  char c;
    37         while( (c=getchar())<48 || c>57)
    38         if(c=='-')Q=-1;
    39         if(Q) res=c-48; 
    40         while((c=getchar())>=48 && c<=57) 
    41         res=res*10+c-48;
    42         return res*Q; 
    43 }
    44 
    45 int main()
    46 {
    47         k = get(); n = get();
    48         for(int i = 1; i <= k; i++)
    49             cin>>a[i].s, a[i].val = get();
    50 
    51         sort(a + 1, a + k + 1, cmp);
    52 
    53         int maxx = 0;
    54         for(int i = 1; i <= k; i++)
    55         {
    56             for(int j = 0; j < n; j++)
    57                 s[n - 1 - j] = a[i].s[j];
    58 
    59             int to = id[string(a[i].s)];
    60 
    61             if(to && A[to].size())
    62             {
    63                 if(A[to][0] - Base + a[i].val > 0)
    64                 {
    65                     if(to == id[string(s)]) maxx = max(maxx, max(a[i].val, A[to][0] - Base) - (A[to][0] - Base + a[i].val));
    66                     Ans += A[to][0] - Base + a[i].val;
    67                     A[to].erase(A[to].begin());
    68                     continue;
    69                 }
    70             }
    71 
    72             to = id[string(s)];
    73             if(!to) to = id[string(s)] = ++total;
    74 
    75             A[to].push_back(a[i].val + Base);
    76         }
    77 
    78         int res = 0;
    79         for(int i = 1; i <= k; i++)
    80         {
    81             int pd = 1;
    82             for(int j = 0; j < n; j++)
    83                 if(a[i].s[n - 1 - j] != a[i].s[j]) {pd = 0; break;}
    84             if(pd == 0) continue;
    85 
    86             int to = id[a[i].s];
    87             if(A[to].size() >= 1)
    88                 res = max(res, A[to][0] - Base);
    89         }
    90 
    91         printf("%d", max(Ans + res, Ans + maxx));
    92 }
    View Code
  • 相关阅读:
    ACdream 1114(莫比乌斯反演)
    ACdream 1148(莫比乌斯反演+分块)
    bzoj2301(莫比乌斯反演+分块)
    hdu1695(莫比乌斯反演)
    hdu4908(中位数)
    bzoj1497(最小割)
    hdu3605(最大流+状态压缩)
    【Leetcode】Add Two Numbers
    【Leetcode】Add Binary
    【Leetcode】Single Number II
  • 原文地址:https://www.cnblogs.com/BearChild/p/7766947.html
Copyright © 2020-2023  润新知