zoukankan      html  css  js  c++  java
  • 替罪羊树

    通过子树大小和树大小的关系进行重构,复杂度均摊logn。

    bzoj3600 没有人的算术

    题目大意:一开始只有0,每次可以把两个数x,y组成(x,y)的形式作为新数,数(a,b)(x,y)的比较以第一维为第一关键字、第二维为第二关键字。操作有:把l和r上的数组成新数赋给k,求[l,r]中最大数的下标(数相同时取小下标)。

    思路:考虑如果维护数的信息,可以用重量平衡树,用替罪羊树,对每个数维护一个vi,vi表示平衡树上区间的中点(rt的区间是[0,1],左子树的是[l,mid],右子树的是[mid,r]),插入的时候找到深度最浅的那个点暴力重构。查询就是在线段树上查区间最值。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define N 100005
    #define M 500005
    #define alp 0.75
    #define LD double
    #define eps 1e-9
    using namespace std;
    char chin(){
        char ch=getchar();
        while(ch!='C'&&ch!='Q') ch=getchar();
        return ch;}
    int in(){
        char ch=getchar();int x=0;
        while(ch<'0'||ch>'9') ch=getchar();
        while(ch>='0'&&ch<='9'){
            x=x*10+ch-'0';ch=getchar();
        }return x;}
    int cmp(LD x,LD y){
        if (x-y>eps) return 1;
        if (y-x>eps) return -1;
        return 0;}
    struct tree{int mx,mp;}tr[N<<2];
    LD vi[M];
    struct point{
        int x,y;
        bool operator==(const point&xx)const{return x==xx.x&&y==xx.y;}
        bool operator<(const point&xx)const{
            return (cmp(vi[x],vi[xx.x])==0 ? cmp(vi[y],vi[xx.y])<0 : cmp(vi[x],vi[xx.x])<0);}
    }bi[M];
    struct use{
        int l,r,sz,po;LD le,re;
        bool operator<(const use&x)const{return bi[po]<bi[x.po];}
    }tp[M],zh[M];
    int ai[N],rt,tt=0,bz=0,uf,zt,id[M],iz;
    tree updata(tree x,tree y){
        tree c;
        if (cmp(vi[x.mx],vi[y.mx])>=0){
            c.mx=x.mx;c.mp=x.mp;
        }else{c.mx=y.mx;c.mp=y.mp;}
        return c;}
    void build(int i,int l,int r){
        if (l==r){tr[i]=(tree){ai[l],l};return;}
        int mid=(l+r)>>1;
        build(i<<1,l,mid);build(i<<1|1,mid+1,r);
        tr[i]=updata(tr[i<<1],tr[i<<1|1]);
    }
    void tch(int i,int l,int r,int x){
        if (l==r){tr[i]=(tree){ai[l],l};return;}
        int mid=(l+r)>>1;
        if (x<=mid) tch(i<<1,l,mid,x);
        else tch(i<<1|1,mid+1,r,x);
        tr[i]=updata(tr[i<<1],tr[i<<1|1]);
    }
    tree ask(int i,int l,int r,int ll,int rr){
        if (ll<=l&&r<=rr) return tr[i];
        int mid=(l+r)>>1;tree c1,c2;
        bool f1,f2;f1=f2=false;
        if (ll<=mid){f1=true;c1=ask(i<<1,l,mid,ll,rr);}
        if (rr>mid){f2=true;c2=ask(i<<1|1,mid+1,r,ll,rr);}
        if (f1&&f2) return updata(c1,c2);
        if (f1) return c1;
        return c2;}
    void upd(int u){tp[u].sz=tp[tp[u].l].sz+1+tp[tp[u].r].sz;}
    bool bal(int u){
        if (cmp((LD)max(tp[tp[u].l].sz,tp[tp[u].r].sz)*1.,alp*(LD)tp[u].sz)>0) return false;
        return true;
    }
    void ins(int &u,int k,point x,LD l,LD r){
        if (!u){
            bi[++bz]=x;ai[k]=bz;
            tp[u=++tt]=(use){0,0,1,bz,l,r};
            vi[bz]=(l+r)/2.;
            return;
        }if (bi[tp[u].po]==x){ai[k]=tp[u].po;return;}
        LD mid=(l+r)/2.;
        if (x<bi[tp[u].po]) ins(tp[u].l,k,x,l,mid);
        else ins(tp[u].r,k,x,mid,r);
        upd(u);
        if (!bal(tp[u].l)||!bal(tp[u].r)) uf=u;
    }
    void dfs(int u){
        if (!u) return;
        dfs(tp[u].l);
        zh[++zt]=tp[u];id[++iz]=u;
        dfs(tp[u].r);
    }
    void reb(int &u,int l,int r,LD ll,LD rr){
        if (l>r){u=0;return;}
        int mid=(l+r)>>1;LD mm=(ll+rr)/2.;
        tp[u=id[iz--]]=zh[mid];
        vi[tp[u].po]=mm;
        tp[u].le=ll;tp[u].re=rr;
        reb(tp[u].l,l,mid-1,ll,mm);
        reb(tp[u].r,mid+1,r,mm,rr);
        upd(u);
    }
    void rebuild(int &u){iz=zt=0;dfs(u);reb(u,1,zt,tp[u].le,tp[u].re);}
    int main(){
        int i,n,m,l,r,k;char ch;
        n=in();m=in();
        for (i=1;i<=n;++i) ai[i]=1;
        build(1,1,n);
        bi[bz=1]=(point){0,0};
        tp[0]=(use){0,0,0,0,0.,0.};
        tp[rt=tt=1]=(use){0,0,1,1,0.,1.};
        for (i=1;i<=m;++i){
            ch=chin();l=in();r=in();
            if (ch=='C'){
                k=in();uf=0;
                ins(rt,k,(point){ai[l],ai[r]},0.,1.);
                if (uf){
                    if (!bal(tp[uf].l)) rebuild(tp[uf].l);
                    if (!bal(tp[uf].r)) rebuild(tp[uf].r);
                }else if (!bal(rt)) rebuild(rt);
                tch(1,1,n,k);
            }else{
                tree cc=ask(1,1,n,l,r);
                printf("%d
    ",cc.mp);
            }
        }
    }
    View Code
  • 相关阅读:
    如何在页面上输出html标签:符号实体【转】
    js sort方法根据数组中对象的某一个属性值进行排序【转】
    原生js判断某个元素是否有指定的class名的几种方法【转】
    js支持的编码转换方法【转】
    windows mysql提示:1045 access denied for user 'root'@'localhost' using password yes 解决方案【转】
    PHP 生成随机数rand()和mt_rand()的区别【转】
    php中var关键字用法【转】
    2020软件工程个人作业06——软件工程实践总结作业
    旺宝的家——事后诸葛亮
    旺宝的家—冲刺总结
  • 原文地址:https://www.cnblogs.com/Rivendell/p/5552289.html
Copyright © 2011-2022 走看看