zoukankan      html  css  js  c++  java
  • 二分,倍增的一些思考(lost my music:可持久化栈)

    浅谈二分

    来自8,17考试模拟24。

    本题:

    单调凸包。(找凸包方向:联系高考数学线性规划)

    弹栈操作是一个个向后弹的。
    序列转换为树上。
    对于树上结构,只需记录父子关系,即可还原出一整棵树。
    因为要可持久化,那么这里的栈也变为了树状。
    只需记录在栈里的父亲即可。
    甚至不用开一个数组作为栈。
    由于单调性,搭配倍增使用,效果更佳。

    二分,倍增的一些思考:

    浅谈二分,倍增
    1、那么普通的数组类型栈由于单调性,且是序列上的连续,可以用二分和倍增快速pop
        (这里的二分指l,r,while循环,check(mid) 的二分)
        2、既然既可以使用二分,也可以使用倍增,那他们的区别在哪儿?
        发现:倍增是学lca时学到的,是用来解决树上问题。可以说他满足单调性,但由于树的特殊性质,无法用二分解决。
        因此出现了倍增数组。良好地解决了树上二分祖先的问题。
        推论:倍增数组也可以用在比树更简单的序列上。他是二分的强化版。
        则二分能解决的问题倍增大多可以解决。
        而大多情况下使用mid二分(也可倍增二进制拆分),是因为直接mid,不是固定log,可能会少一点。
        而倍增i=20~0是二进制拆分,复杂度固定log,与二分上限相同,随机情况下会慢一点点。
        不需要记录一些关系时,倍增的二进制拆分和二分是差不多的。
        但是倍增数组提供了很多灵活而多样的功能,使他比单纯二分的适应性、功能性更强。
        
        附:普通二分的倍增写法:(相比麻烦一点)(但是很帅啊)
        int l,r;
        for(int i,20,0){
            if(check(r-(1<<i)))r=(r-(1<<i))
            else l=(r-(1<<i))-1
        }
      本题代码:

    #include<bits/stdc++.h>
    #define F(i,a,b) for(rg int i=a;i<=b;++i)
    #define il inline 
    #define rg register
    #define LL long long
    #define pf(a) printf("%d ",a)
    #define phn puts("")
    using namespace std;
    int read();
    /*
    弹栈操作是一个个向后弹的。
    序列转换为树上。
    对于树上结构,只需记录父子关系,即可还原出一整棵树。
    因为要可持久化,那么这里的栈也变为了树状。
    只需记录在栈里的父亲即可。
    甚至不用开一个数组作为栈。
    由于单调性,搭配倍增使用,效果更佳。
    
    另:1、那么普通的数组类型栈由于单调性,且是序列上的连续,可以用二分和倍增快速pop
        (这里的二分指l,r,while循环,check(mid) 的二分)
        2、既然既可以使用二分,也可以使用倍增,那他们的区别在哪儿?
        发现:倍增是学lca时学到的,是用来解决树上问题。可以说他满足单调性,但由于树的特殊性质,无法用二分解决。
        因此出现了倍增数组。良好地解决了树上二分祖先的问题。
        推论:倍增数组也可以用在比树更简单的序列上。他是二分的强化版。
        则二分能解决的问题倍增大多可以解决。
        而大多情况下使用mid二分(也可倍增二进制拆分),是因为直接mid,不是固定log,可能会少一点。
        而倍增i=20~0是二进制拆分,复杂度固定log,与二分上限相同,随机情况下会慢一点点。
        不需要记录一些关系时,倍增的二进制拆分和二分是差不多的。
        但是倍增数组提供了很多灵活而多样的功能,使他比单纯二分的适应性、功能性更强。
        
        附:普通二分的倍增写法:
        int l,r;
        for(int i,20,0){
            if(check(r-(1<<i)))r=(r-(1<<i))
            else l=(r-(1<<i))-1
        }
        
    */
    #define N 500010
    int n;
    il double min(const double &x,const double &y){return x<y?x:y;}
    int f[N];LL c[N];
    vector<int>son[N];//要记录1、凸壳倍增祖先。
    int las[N<<1][20+2];LL dep[N];
    int jud(int k,int j,int i){return (c[i]-c[j])*(dep[j]-dep[k])<=(c[j]-c[k])*(dep[i]-dep[j]);}
    void dfs(int x){
        dep[x]=dep[f[x]]+1;
        int p=f[x];
        for(int i=20;i>=0;--i){
            if(las[p][i]<2)continue;
            int t=las[p][i];
            if(jud(las[t][0],t,x))p=t;
        }
        if(p!=1){
            if(jud(las[p][0],p,x))p=las[p][0];
            /*
                找凸包切线:类似于lca抬根。
                要找凸包中最靠前一个不符合条件的点。
                然后去判断他的父节点是否符合条件。
                因为如果倍增跳过了,会一直斜率(i,j)>(j,k)。
                所以要找最后一个(i,j)<=(j,k)的点。
                然后判断他的父节点是否符合。
                凸包对于1要特判。
            */
        }    
        las[x][0]=p;
        F(i,1,20)las[x][i]=las[las[x][i-1]][i-1];
        int ting=son[x].size()-1;
        F(i,0,ting){
            dfs(son[x][i]);
        }
    }
    int main(){
        n=read();
        F(i,1,n)c[i]=read();
        F(i,2,n)f[i]=read(),son[f[i]].push_back(i);
        dfs(1);
        F(i,2,n){
            printf("%.10lf
    ",(double)(c[las[i][0]]-c[i])/(dep[i]-dep[las[i][0]]));
        }
    }
    il int read(){
        int s=0,f=0;char ch;
        while(ch=getchar(),f+=(ch=='-'),!isdigit(ch));
        for(;isdigit(ch);s=s*10+(ch^48),ch=getchar());
        return f?-s:s;
    }
    /*
    g++ 3.cpp -g
    ./a.out
    8
    31516 11930 18726 12481 79550 63015 64275 7608
    1 1 2 4 2 4 5
    
    */
    View Code
    Informatik verbindet dich und mich. 信息将你我连结。
  • 相关阅读:
    258. Add Digits 数位相加到只剩一位数
    7. Reverse Integer 反转整数
    9. Palindrome Number 回文数的判断
    824. Goat Latin山羊拉丁文
    819. Most Common Word 统计高频词(暂未被禁止)
    Angular 2 模板语法
    HTML DOM Style opacity 属性
    Basic concepts (C language) – C 中文开发手册
    JavaScript手册 | JS Array 对象中的fill()方法
    HTML <form> 标签
  • 原文地址:https://www.cnblogs.com/seamtn/p/11370324.html
Copyright © 2011-2022 走看看