题意:给你一个由小写字母和字符'.'组成的字符串,定义了一种操作:若字符串中含有连续两个"." 则将其替换为一个".",持续这样的操作,直到整个字符串再也不能进行这样的操作,定义一个映射f :(string)s->(int)n 给出一个字符串被改写成再也执行不了上述操作所需的操作次数。
给出若干条询问,每次询问都将字符串中的第i位替换为指定的字符,注意:每次询问时修改的字符串是对上一次修改后没有进行操作的字符串进行替换(如果是第一条询问则是对原始字符串进行替换)
求每次询问对应的字符串的f值 即f(s)
这个问题如果纯粹按照题目设计模拟进行,限时2s,在大规模数据时会TLE。
如下代码:
By skyword, contest: Codeforces Round #316 (Div. 2), problem: (C) Replacement, Time limit exceeded on pretest 7, #
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<cstring>
#include<vector>
#include<string>
#include<cmath>
#include<stack>
//#define file
#define maxn 100010
using namespace std;
char s[maxn*3];
int len,num;
int t;
char c;
int solve(char s[])
{
char p[maxn*3];
for(int i=0; i<len; i++)
{
p[i]=s[i];
}
int j=0;
int tmp=0;
while(1)
{
j++;
int z=0;
bool flag=false;
for(int i=tmp; i<(len); i++)
{
//printf("####%d\n",tmp);
if(flag)
{
p[i]=p[i+1];
if(i==(len-z))
{
//printf("####");
break;
}
continue;
}
if(p[i]=='.'&&p[i+1]=='.')
{
tmp=i;
flag=true;
z++;
}
}
if(!flag)
{
return j-1;
}
}
}
int main()
{
scanf("%d%d",&len,&num);
//char p[maxn*3];
scanf("%s",s);
// p[i]=s[i];
getchar();
while(num--)
{
scanf("%d %c",&t,&c);
//scanf("%c",&c);
s[t-1]=c;
int ans=solve(s);
printf("%d\n",ans);
}
}
solve函数就是负责模拟的。可以想象,给出300000规模(上限)的数据的时候可能会造成 大概是(300000+150000)*150000/2 三十亿的计算规模,(主要就是那个二重循环让复杂度接近O(n^2)了),这肯定就超时了
所以后来又想了一个新思路,根本没必要搞那么复杂。。
先扫一遍整个字符串,如果发现连续两个"."的情况,答案就加一,然后对每次询问中的替换:如果由小写字母换成小写字母或者由"."换成"."则显然不影响答案,如果是由字母替换成".",则查询该位置左右的字符,如果有一个"."说明这次更改使得答案增加了一,左右侧都有"."则答案加二
同样的道理,如果替换是由"."换成字母,同样查询左右位置的字符,如果是"."则答案减一,道理同上
code:
By skyword, contest: Codeforces Round #316 (Div. 2), problem: (C) Replacement, Accepted, #
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<cstring>
#include<vector>
#include<string>
#include<cmath>
#include<stack>
//#define file
#define maxn 100010
using namespace std;
char s[maxn*3];
int len,num;
int t;
char c;
int main()
{
scanf("%d%d",&len,&num);
scanf("%s",s);
int ans=0;
for(int i=0;i<len-1;i++)
{
if(s[i]=='.')
{
if(s[i+1]=='.')
{
ans++;
}
}
}
while(num--)
{
scanf("%d %c",&t,&c);
if(s[t-1]>='a'&&s[t-1]<='z')
{
if(c=='.')
{
if(s[t-2]=='.')ans++;
if(s[t]=='.')ans++;
}
}
if(s[t-1]=='.')
{
if(c>='a'&&c<='z')
{
if(s[t-2]=='.')ans--;
if(s[t]=='.')ans--;
}
}
s[t-1]=c;
printf("%d\n",ans);
}
}
这后一份ac的代码是比赛结束后十分钟写出来的。。还是too young啊。。