排序+鏈表 CF——752D

725D

剛拿到題目一臉懵逼

10萬個數字長度十萬??????

哦……字符總數小於十萬

媽的嚇死了,還以爲輸入要超時了


構造一個迴文串,顯然的是,我們可以把兩個相反的字符串加到一個迴文串的兩側,構成新的迴文串。


就這個思路,直接開map離散字符串,然後找一下,如果大於0就加上去,以及:可以在中間放一個本身是迴文串的字符串

然後,對於多個相同的字符串的處理方法,顯然越大越好

所以我們先對所有輸入排序,然後掛鏈表

嗯……數組模擬鏈表


然後就可以做了,不知道爲什麼聯想到當前弧優化(逃


以及一個有趣的問題:如果有兩個是迴文串的字符串,我們是加到兩側還是加一個到中間?

聽起來要很多特判的樣子。。。

其實不用


我們開一個變量ans1存中間那個字符串的貢獻

例如xyz -1,xyz 2這樣,我們可以直接把他們放在兩側,然後ans1=max(ans1,-(-1))

爲什麼?這樣相當於把一個去掉,然後把另外一個放到中間去

可以保證中間只有一個


然後。。我WA了兩次

至今不知道發生了什麼= =???理論上沒區別啊

???

算了。。。OI的世界是玄學的

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<string>
#include<map>
#include<cstring>
#include<ctime>
#include<vector>
#define inf 1e9
#define ll long long
#define For(i,j,k) for(int i=j;i<=k;i++)
#define Dow(i,j,k) for(int i=k;i>=j;i--)
using namespace std;
struct node
{
	string s;
	int v;
}t[100001];
map<string,int> mp;
inline bool cmp(node x,node y){return x.v<y.v;}
int f[300001],nxt[300001],poi[300001],ans,ans1,n,k,tot,cnt;
int main()
{
	ios::sync_with_stdio(false);
	cin>>n>>k;
	For(i,1,n)
		cin>>t[i].s>>t[i].v;
	sort(t+1,t+n+1,cmp);
	For(i,1,n)
	{
		if(!mp[t[i].s])	
		{
			mp[t[i].s]=++tot;
			poi[++cnt]=t[i].v;nxt[cnt]=0;f[tot]=cnt;
		}
		else 	
		{
			int tmp=mp[t[i].s];
			poi[++cnt]=t[i].v;nxt[cnt]=f[tmp];f[tmp]=cnt;
		}
	}
	Dow(i,1,n)
	{
		string ts;
		Dow(j,0,k-1)	ts+=t[i].s[j];
		if(ts==t[i].s)
		{
			int tmp=mp[ts];
			if(tmp&&f[tmp]&&nxt[f[tmp]])
			{
				int v=poi[f[tmp]]+poi[nxt[f[tmp]]];
				if(v>0)	ans+=v,ans1=max(ans1,-poi[nxt[f[tmp]]]),f[tmp]=nxt[nxt[f[tmp]]];
				else ans1=max(ans1,poi[f[tmp]]);
			}else 
			if(tmp&&f[tmp])
			{
				ans1=max(ans1,poi[f[tmp]]);
			}
		}
		else 
		{
			int tmp=mp[ts],tmp1=mp[t[i].s];
			if(tmp&&f[tmp]&&f[tmp1])
			{
				int v=poi[f[tmp1]]+poi[f[tmp]];
				if(v>0)	ans+=v,f[tmp]=nxt[f[tmp]],f[tmp1]=nxt[f[tmp1]];
			}	
		}
	}
	printf("%d",ans1+ans);
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章