Codeforces 752D Santa Claus and a Palindrome map应用

点击打开链接

题意:k个字符数串,每个字符串长度为n ,val<=1e4(1<=k,n<=1e5,n*k<=1e5) 求这些string拼接成回文时能得到的最大val

//组成回文:
类1:A!=R(A) A和R(A)放在字符串两边  && val > 0 
类2:两个相同回文 放在字符串两边 && val>0
中间可以放一个回文 从剩下中最大的未配对的选 maxn 或者 原来配对的回文中与最小负数val配对的哪一个 ans-minn 

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=1e9;
struct cmp
{
    bool operator()(int &a,int &b){
        return a<b;
    }
};
map<string,priority_queue<int,vector<int>,cmp> >mp;//每个string 按value 大->小 
int n,k;
//ans-minn,ans+maxn
int main()
{
	
	cin>>n>>k;
		for(int i=1;i<=n;i++)
		{
			int x;
			string s;
			cin>>s>>x;
			mp[s].push(x);
		}
		int ans=0,minn=0,maxn=0;//
		
		for(map<string,priority_queue<int,vector<int>,cmp> >::iterator it=mp.begin();it!=mp.end();it++)
		{
			string s1=it->first;
			string s2=s1;
			reverse(s2.begin(),s2.end());
			//不是回文两两配对即可 
			if(s1!=s2&&mp.find(s2)!=mp.end())
			{
				while(!mp[s1].empty()&&!mp[s2].empty())
				{
					int k=mp[s1].top()+mp[s2].top();
					mp[s1].pop();
					mp[s2].pop();
					if(k>0)
					{
						ans+=k;
					}
					else
					break;
				}
			} 
			else if(s1==s2)
			{
				while(mp[s1].size()>=2)
				{
					int x=mp[s1].top();
					mp[s1].pop();
					int y=mp[s1].top();
					mp[s1].pop();
					
					if(x+y>0)
					{
						ans+=x+y;
						minn=min(minn,y);//inf+1,-inf 取消一个与最小负数配对的s1放中间 
					}
					else
					{
						//其中一个回文可能放在中间 
						mp[s1].push(x);
						mp[s1].push(y);
						break;
					}
				}
			}
		} 
		for(map<string,priority_queue<int,vector<int>,cmp> >::iterator it=mp.begin();it!=mp.end();it++)
		{
			string s1=it->first;
			string s2=s1;
			reverse(s2.begin(),s2.end());
			//从剩下的回文中选一个最大的放中间 
			if(s1==s2&&!mp[s1].empty())
			{
				maxn=max(maxn,mp[s1].top());
			}
		}
		ans=max(ans-minn,ans+maxn);
		cout<<ans<<endl;
	
	return 0;
} 


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值