• 二分与三分


     设置越界下标确定是否存在
     1 //>=x
     2 while(l<r){
     3     int mid((l+r)>>1);
     4     if(a[mid]>=x) r=mid;
     5     else l=mid+1;
     6 }
     7 //<==x
     8 while(l<r)
     9 {
    10     int mid((l+r+1)>>1);
    11     if(a[mid]<=x) l=mid;
    12     else r=mid-1;
    13 }
    14 //setprecision(3)
    15 while(l+(1e-5)<r)
    16 {
    17     double mid=(l+r)/2;
    18     if(calc(mid)) r=mid;
    19     else l=mid;
    20 }
    21 FOR(i,0,100)
    22 {
    23     double mid((l+r)/2);
    24     if(calc(mid)) r-mid;
    25     else l=mid;
    26 }

    从学oi到现在,二分思想是逐渐发挥其威力的。其思想跟数学归纳法很像:

    并不直接解决问题,而是将问题转化为几个相同的规模较小的问题。对于很简单的子问题(边界条件),直接给出答案。

    对于高级数据结构,像线段树,平衡树都是基于二分思想

    可以说,二分是算法大楼的重要根基之一。

    用二分法配合基础算法打暴力,往往会有意想不到的收获。

     

    对于有单调性的序列,二分能够在O(logn)的时间内进行查找。

     

    具体应用:

    1. 二分查找

    1. binary_search(a+n1,a+n2,k);True 找到 ,False 没找到
    2. Lower_bound(a+n1,a+n2,k[,cmp])

            可以排在值的后面

    1. upper_bound(a+n1,a+n2,k[,cmp])

            必须排在值的后面

    2、二分答案

    对于最大值最小化和最小值最大化的问题,可以二分答案,利用答案倒推。

    经典例题

    A. tree

    给你一个无向带权连通图,每条边是黑色或白色。求一棵最小权的恰好有 need 条白色边的生成树

    WQS二分

    P2619 [国家集训队2]Tree I

    https://www.luogu.org/problemnew/show/P2619

     1 const int MX=100010;
     2 struct edge{int u,v,w,col;}e[MX];
     3 int fa[50010];
     4 int n,m,k,l,r,mid,ans1,cc,t;
     5 void scan()
     6 {
     7     cin>>n>>m>>k;
     8     FOR(i,1,m) {cin>>e[i].u>>e[i].v>>e[i].w>>e[i].col;e[i].u++;e[i].v++;}
     9 }
    10 bool cmp(edge aa,edge bb)
    11 {
    12     return aa.w==bb.w?aa.col<bb.col:aa.w<bb.w;
    13 }
    14 int findf(int x){return fa[fa[x]]==fa[x]?fa[x]:fa[x]=findf(fa[x]);}
    15 bool mg(int x,int y)
    16 {
    17     int t1=findf(x);
    18     int t2=findf(y);
    19     if(t1==t2) return 0;
    20     else {fa[t1]=t2;return 1;}
    21 }
    22 bool kruskal()
    23 {
    24     FOR(i,1,m) if(e[i].col==0) e[i].w+=mid;
    25     FOR(i,1,n) fa[i]=i;
    26     sort(e+1,e+m+1,cmp);
    27     t=ans1=cc=0;
    28     FOR(j,1,m)
    29     {
    30         if(mg(e[j].u,e[j].v))
    31         {
    32             ans1+=e[j].col^1;
    33             cc+=e[j].w;
    34         }
    35         if(t==n-1) break;
    36     }
    37     return ans1<k;
    38 }
    39 void work()
    40 {
    41     l=-105;r=105;
    42     while(l<r)
    43     {
    44         mid=l+r+1 >>1;
    45         if(kruskal()) r=mid-1;
    46         else l=mid;
    47         FOR(i,1,m) if(e[i].col==0) e[i].w-=mid;
    48     }
    49     mid=l;kruskal();
    50     cout<<cc-k*l;
    51 }

     B. Chebnear

      最近,R终于获得了一片他梦寐以求的农场,但如此大的一片农场,想要做好防卫工作可不是一件容易的事。所以R购买了N个守卫,分别让他们站在一定的位置上(守卫不可移动,同一位置上至多有一个守卫)。但是,安排了所有的守卫之后,R才发现,守卫们彼此十分厌恶。经R研究,当某两个守卫距离≤K,他们就会发生争吵;但是,想要守卫们和解也是不难的——只需要R给出的平均工资能使两人满意,他们就会同意和解、成为朋友;当然,如果两个守卫有共同的朋友,他们也会和解成为朋友。R非常不想守卫们争吵,因此他想找出,在能使所有守卫闭嘴的前提下,平均工资的最小值是多少。他想到了一个绝妙的方法,但他忙着去Farm,没时间,所以这个任务就交给你了。

    Sort边权值,从小到打拿 二分选边条数,每次判断不在同一联通快中中点的最小距离

    4. 三分法

    mid1=l+(r-l)/3;mid2=r-(r-l)/3;

    对于单峰函数,最优点会与好点在坏点同侧

    5. 分治解题

     Color zed的刷子宽度只有1,也就是说,一次只能将连续的一排或一列格子涂上颜色(长度任意)。zed想用最少的次数把栅栏全部涂上颜色(注意,一个格子不能重复涂色)

    我理所当然的想用DP做,但是有特殊情况

    解决办法:每次不断往上垒,碰到中断的地方就分治解决,分别枚举

    (其实不需要离散化,>5000的直接丢掉即可)

     

  • 相关阅读:
    计算广告(1):计算广告基础
    shell定时任务
    shell脚本运行报错:-bash: xxx: /bin/sh^M: bad interpreter: No such file or directory
    spark文件读取与保存(scala实现)
    spark中的共享变量(广播变量和累加器)
    spark基本概念与运行架构
    用二维数组输出螺旋方阵(JAVA实现)
    InputStream、InputStreamReader和BufferedReader
    Arrays.sort()自定义排序的实现
    BufferedReader和Scanner
  • 原文地址:https://www.cnblogs.com/universeplayer/p/10655456.html
Copyright © 2020-2023  润新知