HDU5696(分治)

我是看了这位大神写的http://m.blog.csdn.net/article/details?id=51477402

但是他没有做详细的解释,我来以我的理解解释一下。

首先对于区间(1,n)我们找到最小值min和最大值max,则ans[n]=min*max。

记录下min的位置minw,开始递归(1,minw-1)和(minw+1,n)

我称之为左右区间,区间大小为L和R,接下来是重点。

对于区间大小为  max(L,R)  至  n-1  的区间来说,他们必须包含区间(1,n)的最小值

而且他们能包含到区间(1,n)的最大值,所有他们的价值为(1,n)的价值。

对于区间大小为  L 至  R  的区间来说他们可以包含(1,n)的最小值也可以不包含。

选择不包含最小值的区间递归会把他的答案更新,选择包含的区间递归可能更新不到。

比如以下数据  8 22 54 7 89 45  , 7 89 45 的价值比 8 22 54 要大,但是递归为 8 22 54 和 89 45

 更新不到 7 89 45 但是对于ans[4]一定可以包含 7和89,

以上就是为了解释代码 

ans[i]=max(ans[i],ans[i+1]);

是如何工作的。

下面贴上java代码:


import java.util.Scanner;


/*
 * 15
 * 2 3 5 7 8 22 54 7 89 45 2 1 5 6 9
 */




public class Code {
 public static long ans[]=new long[100005];
 public static long arr[]=new long[100005];
 public static int n;
 

     public static void main(String args[]){
      Scanner in=new Scanner(System.in);
      
      while(true){
      
      try {
n=in.nextInt();
for(int i=1;i<=n;i++){
      arr[i]=in.nextLong();
}
 } catch (Exception e) {
break;
 }
      
      
      
      for(int i=1;i<=100000;i++)
      ans[i]=0;
      
      f(1,n);
      
      for(int i=n-1;i>=1;i--){
      /*if(ans[i]==0)
      ans[i]=ans[i+1];*/
      //ans[i]=Math.max(ans[i],ans[i+1]);
      }
      
      for(int i=1;i<=n;i++);
      //System.out.println(ans[i]); 
      }    
     }
     
     public static void f(int l,int r){
      
      if(!(r>=l&&1<=l&&r<=n)) return;
      
      for(int i=l;i<=r;i++)
      System.out.print(arr[i]+" ");
      System.out.println();
      
      if(l==r&&arr[l]*arr[r]>ans[1]) {
      ans[1]=arr[l]*arr[r];
      return;
      }
      
      long min=Integer.MAX_VALUE;
      long max=Integer.MIN_VALUE;
      int minw=0;
      
      for(int i=l;i<=r;i++){
      if(arr[i]>max) max=arr[i];
      if(arr[i]<min){
      min=arr[i];
      minw=i;
      }
      }
      
      if(min*max>ans[r-l+1]) ans[r-l+1]=max*min;
      
      f(l,minw-1);
      f(minw+1,r);
     }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值