Always keep a|

luckydrawbox

园龄:4个月粉丝:1关注:2

P8001 Easy Strings Merging

Link\text{Link}

题意

给定 nn 个 01 串,每次你可以从某个串开头移除一个字符并把它加入一个新串 SS 的末尾。最大化 SS 中相邻两个字符相同的对数。

分析

一段长为 xx 的同样字符中相邻两个字符相同的对数显然为 x1x-1,但如果拆成 kk 段只有 nkn-k 对,所以我们只要使同种字符尽量合起来,总段数尽可能少即可,显然题目给的是 nn 个栈,我们一次性把所有栈顶的 00 取完,再取完所有的 11,再 00… 以此类推,直到全都取完,这样得到的段数肯定最少,相当于把每个栈按字符种类划分成几段,将每段对数依次放在数组中,把每个栈的贡献叠合,就可以计算答案了。

然而这样写完你发现过不了,原来第一次有从 0011 开始取两种情况,聪明的你一定能想到,合理运用三大键 CtrlCV 就可以通过。

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
long long read(){
	long long x=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
void write(long long x){
    if(x<0) putchar('-'),x=-x;
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
const int N=1e6+10;
int n,lst;
ll ans1,d1[N],d2[N],ans2,mx;
int c[N];
int main(){
	n=read();
	for(int i=1,j,D;i<=n;i++){
		j=1;
		while((c[j]=getchar())!='\n')
			c[j++]-='0';
		lst=1;
		if(c[1]^1)
		    D=1;
		else
		    D=2;
		for(int k=2;k<=j;k++)
			if(c[k]^c[k-1]){
				d1[D++]+=k-lst;
				lst=k;
			}
		mx=max(mx,(ll)D-1);
		lst=1;
		if(c[1]^0)
		    D=1;
		else
		    D=2;
		for(int k=2;k<=j;k++)
			if(c[k]^c[k-1]){
				d2[D++]+=k-lst;
				lst=k;
			}
		mx=max(mx,(ll)D-1);
	}
	for(int i=1;i<=mx;i++)
		ans1+=max(d1[i]-1,(ll)0);
	for(int i=1;i<=mx;i++)
		ans2+=max(d2[i]-1,(ll)0);
	write(max(ans1,ans2));
	return 0;
}

本文作者:luckydrawbox

本文链接:https://www.cnblogs.com/luckydrawbox/p/18526569

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   luckydrawbox  阅读(3)  评论(0编辑  收藏  举报  
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起