今天,是暑假集训正式开始的一天,有一场新生归来赛。由于今天明天有些事情,所以就今晚就只能写今天A掉的那俩水题了。。明晚再去研究剩下的三道题。。
好了,废话少说,开始我的第一个博客,这次训练的题解。
首先,A题,水题一道。直接略过,没有什么写题解的必要,不如去看其他的NIM博弈的题。
再就是今天的重点,虽然也是一道水题,不过也还有写一些的必要。
先放题目,
E. 最小距离查询 2014新生归来赛
题目描述
给定一个由小写字母a到z组成的字符串S,其中第i个字符为S[i](下标从0开始)。你需要完成下面两个操作: INSERT c 其中c是一个待输入的字符。你需要在字符串的末尾添加这个字符。保证输入的字符同样是a到z之间的一个小写字母。 QUERY x 其中x是一个输入的整数下标。对于这个询问,你需要回答在S当中和S[x]相等且与x最近的距离。输入保证x在当前字符串中合法。 例如S = "abcaba",如果我们操作: INSERT a 则在S的末端加一个字符a,S变成"abcabaa"。 接下来操作 QUERY 0 由于S[0] = a,在S中出现的离他最近的a在下标为3的位置上,距离为3 - 0 = 3。因此应当输出3。 接下来,如果 QUERY 4 S[4] = b,S中离它最近的b出现在下标为1处,距离为4 - 1 = 3。同样应当输出3。 给定初始字符串S和若干操作,对于每个QUERY,你需要求出相应的距离。
输入格式
输入的第一行是一个正整数 T T(T<=20),表示测试数据的组数。 每组输入数据的第一行是一个初始串S。第二行是一个正整数m( 1<=m<=100000 ),表示总共操作的数量。接下来m行,每行表示一个操作。操作的格式如上所述。 数据保证在任何情况下,S的长度不会超过100000。 OutputFormat 对于每个QUERY,输出所求的最小距离。如果S中其它位置都不存在和它相同的字符,输出-1。
输出格式
对于每个QUERY,输出所求的最小距离。如果S中其它位置都不存在和它相同的字符,输出-1。
输入样例
2
axb
3
INSERT a
QUERY 0
QUERY 1
explore
3
INSERT r
QUERY 7
QUERY 1
输出样例
3
-1
2
-1
我用了一个动态数组来存储相同字母出现的位置,然后每添加一次就维护一次,查询时用二分进行查找。
咱分析题目中出现的字符串,首先,第一次输入的字符串,拿样例来举例的吧,比如,axb,从头到尾,每出现一个字母,就把他存到对应的数组中,比如这个单词,就有
a['a'-'a'][0]=0,a['x'-'a'][0]=1,a['b'-'a'][0]=2;然后就有添加一个a,由于原来已经存在一个a了,所以这次应该是a['a'-'a'][1]=3,着用动态数组很容易实现 ; 其他的例子也是如此。
那么,查找该怎么办呢?很容易看出来,存入数组之后,数组所记录的数据时有序的,有序就简单了,二分法,只有logn的复杂度,肯定不会超时。(弱渣写个二分还出了好多问题)
下面贴代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
using
namespace
std;
#define N 100005
char
s[N]={0};
vector<
int
> a[30];//动态数组存储位置,下标代表字母。
void
init()
{
memset
(s,0,
sizeof
(s));
for
(
int
i=0;i<=26;i++)
a[i].clear();
}
int
divideSearch(
int
ch,
int
n)//二分查找
{
int
l=0,r=a[ch].size()-1;
int
mid=(l+r)/2;
if
(a[ch].size()==1)
return
-1;
if
(a[ch][l]==n) mid=l;
if
(a[ch][r]==n) mid=r;
while
(a[ch][mid]!=n)
{
if
(a[ch][mid]>n) r=mid;
if
(a[ch][mid]<n) l=mid;
mid=(l+r)/2;
if
(a[ch][l]==n) mid=l;
if
(a[ch][r]==n) mid=r;
}
if
(mid==0)
return
a[ch][1]-a[ch][0];
else
if
(mid==a[ch].size()-1)
return
a[ch][a[ch].size()-1]-a[ch][a[ch].size()-2];
return
min(a[ch][mid+1]-a[ch][mid],a[ch][mid]-a[ch][mid-1]);
}
int
main()
{
int
t;
cin>>t;
while
(t--)
{
init();
int
m;
scanf
(
"%s"
,s);
int
length=
strlen
(s);
for
(
int
i=0;i<length;i++)
{
a[s[i]-
'a'
].push_back(i);
}
scanf
(
"%d"
,&m);
for
(
int
i=1;i<=m;i++)
{
char
order[10];
scanf
(
"%s"
,order);
if
(
strcmp
(order,
"INSERT"
)==0)
{
char
ch;
scanf
(
"%s"
,&ch);
a[ch-
'a'
].push_back(length);
s[length]=ch;
length++;
s[length]=
'\0'
;
}
else
if
(
strcmp
(order,
"QUERY"
)==0)
{
int
n;
scanf
(
"%d"
,&n);
int
ans=divideSearch(s[n]-
'a'
,n);
printf
(
"%d\n"
,ans);
}
}
}
}
今天就到这里,等后天研究完剩下的题目,依然会继续发题解的。