Santa Claus and a Palindrome
Time Limit: 20 Sec Memory Limit: 512 MBDescription
有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
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 }