今天,是暑假集训正式开始的一天,有一场新生归来赛。由于今天明天有些事情,所以就今晚就只能写今天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,你需要求出相应的距离。
输入格式
输入的第一行是一个正整数TT(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> usingnamespace
std;#define
N 100005chars[N]={0};vector<int>
a[30];//动态数组存储位置,下标代表字母。voidinit(){ memset(s,0,sizeof(s)); for(inti=0;i<=26;i++) a[i].clear();}intdivideSearch(intch,intn)//二分查找{ intl=0,r=a[ch].size()-1; intmid=(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) returna[ch][1]-a[ch][0]; elseif(mid==a[ch].size()-1) returna[ch][a[ch].size()-1]-a[ch][a[ch].size()-2]; returnmin(a[ch][mid+1]-a[ch][mid],a[ch][mid]-a[ch][mid-1]);}intmain(){ intt; cin>>t; while(t--) { init(); intm; scanf("%s",s); intlength=strlen(s); for(inti=0;i<length;i++) { a[s[i]-'a'].push_back(i); } scanf("%d",&m); for(inti=1;i<=m;i++) { charorder[10]; scanf("%s",order); if(strcmp(order,"INSERT")==0) { charch; scanf("%s",&ch); a[ch-'a'].push_back(length); s[length]=ch; length++; s[length]='\0'; } elseif(strcmp(order,"QUERY")==0) { intn; scanf("%d",&n); intans=divideSearch(s[n]-'a',n); printf("%d\n",ans); } } }}
今天就到这里,等后天研究完剩下的题目,依然会继续发题解的。
本文详细解析了一种解决最小距离查询问题的算法。通过使用动态数组存储相同字符出现的位置,并结合二分查找的方法,实现了高效的查询操作。适用于字符串操作及查询场景。
1870

被折叠的 条评论
为什么被折叠?



