中南 1294 coins 重点是想法,外加STL中的map
题目网址:http://122.207.68.93/OnlineJudge/problem.php?id=1294
题意是给你一个字符串,字符串中只包含O和R,要你求满足条件的最长的连续子序列的长度,输出该长度。。条件是,连续子序列中O的个数是R的个数的K倍(K已知)
想法如下:
设这个满足条件的子序列O的个数为x,R的个数为y
则有x = k*y
即有x + (-k)*y = 0
那么如果令R的权值为-k,O的权值为1,这段序列的和即为0
令sum[i]为前i项之和。。。如果有sum[i] == sum[j],证明a(i+1) + a(i+2) + ```` + a(j)的和为0,也就是说出现可行解,其长度为j-i...
线性扫一遍,查找是否出现重复值就用map,降低时间复杂度
所以大概的复杂度就是O(n*logn)...
贴代码:
1 #include <cstdio> 2 #include <map> 3 #include <cstring> 4 #define LL long long int 5 using namespace std; 6 int main() 7 { 8 // freopen("in.cpp","r",stdin); 9 int len,k; 10 scanf("%d%d",&len,&k);//长度和K值 11 char a; 12 int max = 0;//用来记录最后的结果,初始状态为0 13 map<LL,int> m; 14 LL sum = 0; 15 m[0] = 0; 16 getchar(); 17 for(int i=1; i<=len; ++i) 18 { 19 a = getchar(); 20 if(a == 'O') 21 ++sum;//O,加1 22 else sum -= k;//R,加-K 23 map<LL,int>::iterator it; 24 it = m.find(sum); 25 if(it != m.end())//出现重复 26 { 27 if(max < i-(*it).second)//出现更大长度 28 max = i-(*it).second;//更新MAX 29 } 30 else 31 m[sum] = i;//未出现重复,保存 32 } 33 printf("%d\n",max); 34 return 0; 35 }