zoukankan      html  css  js  c++  java
  • 冯泽来学分块(二分查找)

    冯泽来 最近在学分块,但是他太菜了,分的块数量太多他就混乱了,所以只能分成3 块
    今天他得到了一个数组,他突然也想把它分块,他想知道,把这个数组分成3 块,块可以为空。假设3 块各
    自的和中的最大值最小
    请输出分完之后3 块中的最大值
    输入
    输入第一行包含一个整数n 代表数组大小
    接下来n 个整数a1, a2, ..., an,代表数组
    对于40% 的数据,1≤n≤10
    对于70% 的数据,1≤n≤10的3次方
    对于100% 的数据,1≤n≤105, 1≤ai≤10的7次方

    样例输入1

    10

    2 5 1 4 7 3 6 2 5 1

    样例输出1

    14

    先用sum[i]统计1到i的和,最后处理的时候用sum[i]-sun[j-1]就可以得到j到i区间的和了。

    然后枚举i点,在后面的区间中用二分求出另一个分界点

    代码:

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    using namespace std;
    long long sum[100005],a[100005];
    long long ans=111111111111LL;
    long long max(long long a,long long b,long long c)
    {
      if(a>b&&a>c)return a;
      if(b>a&b>c)return b;
      return c;
    }
    int main()
    {
      freopen("divide.in","r",stdin);
      freopen("divide.out","w",stdout);
      ios::sync_with_stdio(false);
      int n;cin>>n;
      for(int i=1;i<=n;i++)
      {
        cin>>a[i];
        sum[i]=sum[i-1]+a[i];
      }
      for(int i=1;i<=n;i++)
      {
        int left=i+1,right=n+1;
        while(left<right-1)
        {
          int mid=left+right>>1;
          if(sum[mid-1]-sum[i-1]<=sum[n]-sum[mid-1])
          left=mid;
          else right=mid;
        }
        long long ans1=sum[left-1]-sum[i-1];
        long long ans2=sum[n]-sum[left-1];
        ans=min(ans,max(sum[i-1],ans1,ans2));
        ans1=sum[left]-sum[i-1];
        ans2=sum[n]-sum[left];
        ans=min(ans,max(sum[i-1],max(ans1,ans2)));
      }
      cout<<ans;
      return 0;
    }

  • 相关阅读:
    zzuli--2134: 维克兹的进制转换(规律)
    hdu--1316--How Many Fibs?(java大数)
    NYOJ--517--最小公倍数(大数打表)
    NYOJ--513--A+B Problem IV(大数)
    NYOJ--45--棋盘覆盖(大数)
    NYOJ--114--某种序列(大数)
    HAUT--1262--魔法宝石(暴力)
    NYOJ--1276--机器设备(河南省第九届省赛,简单的bfs)
    hdu--1429--胜利大逃亡(续) (bfs+状态压缩)
    NYOJ--541--最强DE 战斗力(递推)
  • 原文地址:https://www.cnblogs.com/937337156Zhang/p/5671541.html
Copyright © 2011-2022 走看看