【CF676C】Vasya and String(二分查找,线性扫描尺取法)

题意:

给出一个长度为n的字符串,只有字符‘a‘和‘b‘。最多能改变k个字符,即把‘a‘变成‘b‘或把‘b‘变成‘a‘。

问改变后的最长连续相同字符的字串长度为多少。

首先是二分查找,好想也好写

 1 var s:array[0..100000]of longint;
 2     ch:ansistring;
 3     n,k,i,l,r,mid,last,ans:longint;
 4
 5 function max(x,y:longint):longint;
 6 begin
 7  if x>y then exit(x);
 8  exit(y);
 9 end;
10
11 begin
12  //assign(input,‘1.in‘); reset(input);
13  //assign(output,‘1.out‘); rewrite(output);
14  readln(n,k);
15  readln(ch);
16  for i:=1 to n do
17  begin
18   s[i]:=s[i-1];
19   if ch[i]=‘b‘ then inc(s[i]);
20  end;
21  ans:=0;
22  for i:=1 to n do
23   begin
24   l:=i; r:=n; last:=i;
25   while l<=r do
26   begin
27    mid:=(l+r)>>1;
28    if s[mid]-s[i-1]<=k then begin last:=mid; l:=mid+1; end
29     else r:=mid-1;
30   end;
31   ans:=max(ans,last-i+1);
32  end;
33  fillchar(s,sizeof(s),0);
34  for i:=1 to n do
35  begin
36   s[i]:=s[i-1];
37   if ch[i]=‘a‘ then inc(s[i]);
38  end;
39  for i:=1 to n do
40   begin
41   l:=i; r:=n; last:=i;
42   while l<=r do
43   begin
44    mid:=(l+r)>>1;
45    if s[mid]-s[i-1]<=k then begin last:=mid; l:=mid+1; end
46     else r:=mid-1;
47   end;
48   ans:=max(ans,last-i+1);
49  end;
50  writeln(ans);
51  //close(input);
52  //close(output);
53 end.

然后是线性扫描,ACM叫做尺取法,机房大神叫伸头缩尾法

l循环后还要+1是因为要到下一段连续区间的开头,而当前连续间的字母和下一段一定不同(显然要找最长的连续相同序列)

 1 var ch:ansistring;
 2     n,k,ans,r,l,i,t:longint;
 3
 4 function max(x,y:longint):longint;
 5 begin
 6  if x>y then exit(x);
 7  exit(y);
 8 end;
 9
10 begin
11  //assign(input,‘1.in‘); reset(input);
12  //assign(output,‘1.out‘); rewrite(output);
13  readln(n,k);
14  readln(ch);
15  l:=1; r:=1; t:=0;
16  for i:=1 to n do
17  begin
18   if ch[i]=‘b‘ then
19   begin
20    if t<k then begin inc(t); inc(r); end
21     else
22     begin
23      while (l<=n)and(ch[l]=‘a‘) do inc(l);
24      inc(l);
25      inc(r);
26     end;
27   end
28    else inc(r);
29   ans:=max(ans,r-l);
30  end;
31  l:=1; r:=1; t:=0;
32  for i:=1 to n do
33  begin
34   if ch[i]=‘a‘ then
35   begin
36    if t<k then begin inc(t); inc(r); end
37     else
38     begin
39      while (l<=n)and(ch[l]=‘b‘) do inc(l);
40      inc(l);
41      inc(r);
42     end;
43   end
44    else inc(r);
45   ans:=max(ans,r-l);
46  end;
47  writeln(ans);
48  //close(input);
49  //close(output);
50 end.

时间: 2024-10-10 03:02:27

【CF676C】Vasya and String(二分查找,线性扫描尺取法)的相关文章

POJ3061 Subsequence(二分前缀和法+尺取法)

二分+前缀和法 满足条件的子序列长度在(0,n)之间,sum[x+i]-sum[i]为从从第i个元素开始序列长度为x的元素的和.前缀和可在O(n)的时间内统计 sum[i]的值.再用二分找出满足条件的最小的子序列长度. #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<queue> #

折半查找/二分查找 以及二叉树的 三种遍历方式

二分查找   线性查找 1.二分查找 public class BinarySearch { /** * 二分查找 * @param data * @return */ public int binarySearch(long[] data,long n) { //左右 端点 int left =0; int right =data.length-1; //中间元素 int mid=-1; while(left<right){ // 有两种情况 1.left = right 2. left>r

java数组回顾---线性查找最大值最小值---二分查找

import java.util.Scanner; public class ArrayDemo { public static void main(String []args) { //------------------------------------------------------- //线性查找 int [] num ={10,20,30,40,50}; Scanner input1 = new Scanner(System.in); System.out.println("请输

线性结构--二分查找

二分查找又称折半查找,它是一种效率较高的查找方法. 二分查找要求:线性表是有序表,即表中结点按关键字有序,并且要用向量作为表的存储结构.不妨设有序表是递增有序的. 二分查找java代码 1 package com.feimao.com.feimao.a2.test; 2 3 import java.util.Arrays; 4 5 public class BinarySerach { 6 public static void main(String[] args){ 7 int[] arr =

转:线性表的查找-二分查找

转自:http://student.zjzk.cn/course_ware/data_structure/web/chazhao/chazhao9.2.2.1.htm 二分查找 1.二分查找(Binary Search)     二分查找又称折半查找,它是一种效率较高的查找方法.    二分查找要求:线性表是有序表,即表中结点按关键字有序,并且要用向量作为表的存储结构.不妨设有序表是递增有序的. 2.二分查找的基本思想    二分查找的基本思想是:(设R[low..high]是当前的查找区间) 

List&lt;T&gt;线性查找和二分查找BinarySearch效率分析

今天因为要用到List的查找功能,所以写了一段测试代码,测试线性查找和二分查找的性能差距,以决定选择哪种查找方式. 线性查找:Contains,Find,IndexOf都是线性查找. 二分查找:BinarySearch,因为二分查找必须是对有序数组才有效,所以查找前要调用List的Sort方法. 结论:如果List项的个数比较小,用线性查找要略快于二分查找,项的个数越多二分算法优势越明显.可根据实际情况选用适合的查找方式. 测试结果: 测试代码: private void button1_Cli

看数据结构写代码(53) 静态查找表(线性查找,二分查找,斐波那契查找,插值查找)

查找定义:根据给定的某个值,在查找表中确定一个其关键字等于给定值的数据元素(或记录). 查找表分类:静态查找表和动态查找表. 静态查找表:只查找,而不进行插入,删除. 动态查找表:在查找过程中同时插入查找表中不存在的数据元素,或者从查找表中删除已经存在的某个数据元素. 静态表的 查找 大致 四种 算法: 线性查找,二分查找,斐波那契查找和插值查找. 其中 在线性查找之前,对表 无要求.对于 其余三种 需要 在查找之前 排序.插值查找 除了 需要 排序,还需要 均匀分布. 下面 给出代码: 线性查

算法之二分查找PK线性查找

列表查找(线性查找) 本质就是列表的index() 顺序查找 也叫线性查找,从列表第一个元素开始,顺序进行搜索,知道找到元素或搜索到列表最后一个元素为止. 以下是示例代码: def line_search(li, val): for key, value in enumerate(li): if value == val: return key else: return None 二分法查找(前提必须是一个有序的列表) 通过取中间值,选择候选区,如果中间值大于要查找的值,则证明候选区在左边,更改

Java学习 (七)、数组,查找算法,二分查找法,冒泡排序,选择排序,插入排序

一.常用数组查找算法 工作原理:它又称为顺序查找,在一列给定的值中进行搜索,从一端的开始逐一检查每个元素,知道找到所需元素的过程. 例1:查找指定的数在数组中出现的位置,找到返回下标,找不到返回-1 1 import java.util.Scanner; 2 public class LinearSearch{ 3 public static void main(String []argas) 4 { 5 int [] array={10,100,90,65,80,92}; 6 System.o