poj2566Bound Found尺取法进阶(java)

简介: 这个尺取法的思想挺好的,如果第一次做尺取法题,不妨看下尺取法入门题。

这个尺取法的思想挺好的,如果第一次做尺取法题,不妨看下尺取法入门题。


题目大意:



多组测试数据(0,0)截止。

每组数据输入 n,k(n数字个数,k询问次数)

下一行n个数表示序列。

接下一行k个表示询问,表示找到一个子序列和的绝对值最接近k。每个询问输出三个数 分别是子序列和的绝对值,子序列头和尾。


分析:



传统暴力,数值量太高O(n^2)肯定直接爆炸。


本来从别人尺取法看到本题。发现这有负数,sum不单调怎么玩。苦苦没有想法。后来简单看了别人思路:求和排序 尺取法。


sum好求。求完排序初始的序列不是都乱了么,最后还怎么输出?所以这个要用到结构体或者二维数组根据sum排序。你可以用sum[][2]数组其中一个是sum求和,另一个是初始标记。我们在执行的过程中不需要考虑标记,只需要最后输出时候再考虑。


求和数组排完序列的处理也是棘手的,因为sum就算单调了,但是sum有正负之分。如果这样处理起来也很麻烦,但是有一个好方法:sum求差。sum差的含义是两点之间的序列和。这样我只在乎序列和的大小。不用在乎你的正负关系。我只需要知道你们两之间的序列差的绝对值是那么大。但是这样缺少一种情况—sum[i];但是我们可以引入一个sum[0],sum[1]到sum[n]减去sum[0]就是自身。就能保证所有情况。


所以具体思路就是:先把数组求和,然后排序,并把对应的初始序号也计下。然后使用尺取法,left,right=0,right从1到n遍历,看sum[right]-sum[left]是否与已知绝对值靠近,如果满足情况更新对应的L,R,和value.因为他不需要找最短或者最长序列,找到满足即可。也减少了难度。最后L和R是对应value=sum[R]-sum[L].找到R和L对应的序列编号,min对应小的,max对应大的(min,max对应L,R排序前实际位置一个为小编号一个为大),其实|value|=|sum[max]-sum[min]|,实际上序列不包含min那个节点,所以最后输出value min 1 max.


还有一点比较坑的是,他的测试用例有问题。。他又16个-1.是挺坑的,打断点调了很久。


下面附上java ac代码



import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.Arrays;
import java.util.Comparator;
public class poj2566 {
  static int left=0;
  static int right=0; 
  static int minlen=0;
  public static void main(String[] args) throws IOException {
    // TODO 自动生成的方法存根
    StreamTokenizer in=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
    PrintWriter out=new PrintWriter(new OutputStreamWriter(System.out));
    while(in.nextToken()!=StreamTokenizer.TT_EOF)
    {
      int n=(int)in.nval;
      in.nextToken();int k=(int)in.nval;
      if(n==0&&k==0) {break;}
      int a[]=new int[n];int sum[][]=new int[n 1][2];
      for(int i=0;isum[right][0]?sum[left][0]:sum[right][0];
        System.out.println((min 1) " " max);
      }     
    }
  }
  private static void chiqu(int[][] sum2, int team) {
    // TODO 自动生成的方法存根
    int l=0;
    for(int i=1;i=team&&lcomparator=new Comparator() {
    @Override
    public int compare(int[] o1, int[] o2) {
      // TODO 自动生成的方法存根
      return o1[1]-o2[1];
    }
  };
}


如果代码有什么错误请大佬指正!?;

目录
相关文章
|
4月前
|
Java Perl
Java进阶之正则表达式
【7月更文挑战第17天】正则表达式(RegEx)是一种模式匹配工具,用于在字符串中执行搜索、替换等操作。它由普通字符和特殊元字符组成,后者定义匹配规则。
34 4
|
4月前
|
设计模式 Java
Java进阶之代理
Java进阶之代理
26 4
|
4月前
|
设计模式 Java
Java进阶之代理
Java进阶之代理
30 3
|
4月前
|
设计模式 Java
Java进阶之代理
【7月更文挑战第16天】Java动态代理通过`java.lang.reflect.Proxy`和`InvocationHandler`实现,无需编译期定义代理类。与静态代理相比,它更灵活,代码更简洁,适用于方法数量变化或未知接口代理。
29 2
|
4月前
|
Java
Java进阶之内部类
【7月更文挑战第13天】Java内部类增进代码组织与封装,允许直接访问外部类成员,包括私有成员。主要有四种类型:成员、静态、局部和匿名内部类。匿名内部类常用于一次性实现接口或扩展类。内部类可隐藏实现细节,减少命名冲突,并在特定上下文中定义辅助类。示例展示了静态和非静态内部类如何在Shape类中封装Circle和Rectangle。使用内部类能提升代码可读性,但可能增加复杂性。
37 6
|
4月前
|
Java 编译器 API
Java进阶之标准注解
【7月更文挑战第15天】Java标准注解包括标记注解(如@Deprecated)、@Override(检查方法重写)、@SuppressWarnings(抑制警告)。多值注解如@RequestMapping在Spring中用于HTTP请求映射。元注解如@Retention控制注解保留策略,@Target指定应用位置。Java8引入类型注解(@FunctionalInterface、@SafeVarargs)和重复注解(@Repeatable)。自定义注解可通过反射读取,如示例中的MyMarkerAnnotation等。
26 2
|
4月前
|
安全 Java
Java进阶之枚举
【7月更文挑战第11天】Java枚举是Java 5引入的特性,用于定义固定常量集合,如星期。枚举是继承自`java.lang.Enum`的特殊类,编译后成为final类,每个枚举值是静态final实例。定义枚举用`enum`关键字,如`public enum Weekday {MONDAY, TUESDAY, ...}`。枚举可包含方法和变量,能实现接口但不能继承其他类。例如,`Weekday`枚举可实现`Describe`接口,提供`describe()`方法。在实际应用中,枚举常用于表示如响应状态等固定选项,便于类型安全和代码阅读。
39 8
|
4月前
|
Java 编译器 API
Java进阶之标准注解
Java进阶之标准注解
30 1
|
4月前
|
IDE Java 测试技术
Java进阶之反射
【7月更文挑战第14天】Java反射机制允许在运行时动态获取类信息、创建对象及调用其方法。它基于`Class`类,让我们能访问类的属性、方法、构造器。例如,通过`Class.forName()`加载类,`Class.newInstance()`创建对象,`Method.invoke()`执行方法。反射广泛应用于动态代理、单元测试、序列化及框架中,提供灵活性但牺牲了性能,且可破坏封装性。IDE的代码补全也是反射的应用之一。在使用时需谨慎,避免对私有成员的不当访问。
39 1
|
4月前
|
Java
Java进阶之函数式编程
Java进阶之函数式编程
33 3
下一篇
无影云桌面