关闭

Codeforces Round #389 (Div. 2, Rated, Based on Technocup 2017 - Elimination Round 3) D

204人阅读 评论(0) 收藏 举报
分类:

题意:

圣诞老人的朋友送给了他k个长度均为n的字符串,他对第i个字符串有一个喜爱度,,记作ai,ai可正可负。

现在,圣诞老人想在这k个串中调出一些串,使得它们通过某种顺序收尾拼接后能形成一个回文串,在此基础上,还要让选择的串的权值和最大。注意,空串也属于回文串,因此,答案不会小于0。n*k <= 1E5


solution:

假如选出了奇数个串,那么中间那个串自己必须是回文串,同时,从中间向两边延伸,字符串一一匹配。若串A翻转以后得到串B,那么就说A和B匹配。如果选出的串是偶数个,就不考虑存在中间串的情形

那么,,现在先对每个串正向,逆向各hash一遍,枚举每种类型的串,同时枚举该类型的翻转串。贪心地想,每次要选出的匹配对一定是权值和最大的,这样贡献也就最大。因此,对于每个类型,尽量挑最大的塞进去就行了。如果答案选出的串是奇数个,那么先挑作为中心串的串,当然是拿权值最大的,然后在匹配

用类似前缀/后缀和的方式加速就行了


注意。。。cf的数据非常好,,,用自然溢出会被卡掉= =以后字符串hash再也不写自然溢出了。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
#include<cmath>
using namespace std;

typedef unsigned long long UL;
typedef long long LL;
const UL p = 233;
const UL mo = 1000000007;
const int maxn = 1E5 + 10;

UL A[maxn*2],h[maxn][2];
int k,n,tot,cur = 1,a[maxn],Num[maxn][2],G[maxn*2];
LL Ans,sum[maxn*2][2],sl[maxn*2],sr[maxn*2];
char s[maxn];

vector <int> v0[maxn*2],v1[maxn*2];

UL Mul(const UL &x,const UL &y) {return x*y%mo;}
UL Add(const UL &x,const UL &y) {return (x + y) % mo;}

bool cmp(const int &x,const int &y) {return a[x] > a[y];}

int main()
{
	#ifdef DMC
		freopen("DMC.txt","r",stdin);
	#endif
	
	cin >> k >> n;
	for (int i = 1; i <= k; i++)
	{
		scanf("%s%d",s + 1,&a[i]);
		for (int j = 1; j <= n; j++)
		{
			h[i][0] = Mul(h[i][0],p);
			h[i][0] = Add(h[i][0],s[j]);
		}
		for (int j = n; j; j--)
		{
			h[i][1] = Mul(h[i][1],p);
			h[i][1] = Add(h[i][1],s[j]);
		}
		A[++tot] = h[i][0]; A[++tot] = h[i][1];
	}
	sort(A + 1,A + tot + 1);
	for (int i = 2; i <= tot; i++)
		if (A[i] != A[i-1]) A[++cur] = A[i];
	for (int i = 1; i <= k; i++)
	{
		Num[i][0] = lower_bound(A + 1,A + cur + 1,h[i][0]) - A;
		Num[i][1] = lower_bound(A + 1,A + cur + 1,h[i][1]) - A;
		v0[Num[i][0]].push_back(i); G[Num[i][0]] = Num[i][1];
		v1[Num[i][1]].push_back(i); G[Num[i][1]] = Num[i][0];
	}
	for (int i = 1; i <= cur; i++)
	{
		sort(v0[i].begin(),v0[i].end(),cmp);
		sort(v1[i].begin(),v1[i].end(),cmp);
	}
	
	for (int i = 1; i <= cur; i++)
	{
		if (G[i] > i) continue;
		if (G[i] == i)
		{
			for (int j = 0; j < v0[i].size()-1; j += 2)
			{
				int now = a[v0[i][j]] + a[v0[i][j+1]];
				if (now < 0) break; sum[i][0] += 1LL*now;
			}
			sum[i][1] = a[v0[i][0]];
			for (int j = 1; j < v0[i].size()-1; j += 2)
			{
				int now = a[v0[i][j]] + a[v0[i][j+1]];
				if (now < 0) break; sum[i][1] += 1LL*now;
			}
		}
		else
		{
			int siz = min(v0[i].size(),v1[i].size());
			for (int j = 0; j < siz; j++)
			{
				int now = a[v0[i][j]] + a[v1[i][j]];
				if (now < 0) break; sum[i][0] += 1LL*now;
			}
		}
	}
	for (int i = 1; i <= cur; i++) sl[i] = sum[i][0] + sl[i-1];
	for (int i = cur; i; i--) sr[i] = sum[i][0] + sr[i+1];
	for (int i = 1; i <= cur; i++)
		Ans = max(Ans,sl[i-1] + sum[i][1] + sr[i+1]);
	cout << max(Ans,sl[cur]);
	return 0;
}

0
0
查看评论

Codeforces Round #445 (Div. 1, based on Technocup 2018 Elimination Round 3) E. Mod Mod Mod

E. Mod Mod Mod time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard output You are given a sequence...
  • zstu_zy
  • zstu_zy
  • 2017-12-01 17:11
  • 60

Educational Codeforces Round 36 (Rated for Div. 2) 题解

先总结一波 第一次打cf,感觉还不错,题目做得挺顺手。虽然开始30min才想起来有这么个比赛来着。。 纪念一下第一次的rank,话说题真是水 这是大概还剩下5min的时候截的,实际可能会掉一点吧 第二天更新: 原来d题真的会被卡,果然还是要tarjan找一个环来删边 hackin...
  • jpwang8
  • jpwang8
  • 2018-01-13 23:16
  • 230

Codeforces Round #258 (Div. 2)-(A,B,C,D,E)

A:Game With Sticks 水题。。。每次操作,都会拿走一个横行,一个竖行。 所以一共会操作min(横行,竖行)次。 #include #include #include #include #include #include #include #include #pragma commen...
  • rowanhaoa
  • rowanhaoa
  • 2014-07-25 14:39
  • 1467

Educational Codeforces Round 33 (Rated for Div. 2) F. Subtree Minimum Query (线段树)

题目链接:http://codeforces.com/contest/893/problem/F 这个题好像挺傻逼的啊? 首先dfs序,然后线段树维护,每个节点维护一个vector表示这个区间中所有的节点的深度,这样的空间复杂度为O(nlogn),因为不涉及修改,咱们的对每个节点的vector都...
  • sinat_32872703
  • sinat_32872703
  • 2017-11-29 20:47
  • 84

Educational Codeforces Round 36 (Rated for Div. 2) C 不大于某个数的序列变换

C. Permute Digitstime limit per test1 secondmemory limit per test256 megabytesinputstandard inputoutputstandard outputYou are given two positive integ...
  • Little_boy_z
  • Little_boy_z
  • 2018-01-19 12:42
  • 30

Codeforces Round #460 (Div. 2) D. Substring(拓扑排序)

题目链接题意:有一个n个点m条边的有向图,每个节点有一个字母,路径的权值是路径上相同字母的最大个数。求最大的路径权值。思路:因为只有26个字母,所以直接假设其中一个字母为相同字母数最大的字母。枚举每一个字母,通过拓扑排序找到最大权值,取其中的最大值就是答案。当图中存在环时,答案就是无穷大,输出-1;...
  • cyf199775
  • cyf199775
  • 2018-02-01 13:55
  • 33

Codeforces Round #413 Div. 2 D. Field expansion

D. Field expansion time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard output In one of the games A...
  • qq_33183401
  • qq_33183401
  • 2017-05-14 22:52
  • 198

Educational Codeforces Round 37 (Rated for Div. 2)【A B C】【水】【模拟】

嗖的一下! A #include using namespace std; #define ll long long int a[500]; int c[500]; int main() { int N; cin >> N; while(N--) { ...
  • Head_Hard
  • Head_Hard
  • 2018-02-03 16:18
  • 53

Codeforces Round #327 (div.2)(A B C D)

codeforces round #327 (div.2)
  • lincifer
  • lincifer
  • 2015-10-26 13:11
  • 1084

Codeforces Round #427 (Div. 2) A B C D

A. Key races time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Two boys decided ...
  • sinat_35406909
  • sinat_35406909
  • 2017-08-01 02:03
  • 693
    个人资料
    • 访问:200794次
    • 积分:8912
    • 等级:
    • 排名:第2547名
    • 原创:733篇
    • 转载:1篇
    • 译文:0篇
    • 评论:16条
    文章分类
    最新评论