zoukankan      html  css  js  c++  java
  • 51 nod 1297 管理二叉树

    原题链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1297

    先是暴力加优化T了最后两个点……

    我还是来想想正解吧。

    先写棵线段树把二叉搜索树建出来,然后在树上做下点分治就好了。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define lp (p<<1)
    #define rp ((p<<1)|1)
    using namespace std;
    
    int read_p,read_ca;
    inline int read(){
        read_p=0;read_ca=getchar();
        while(read_ca<'0'||read_ca>'9') read_ca=getchar();
        while(read_ca>='0'&&read_ca<='9') read_p=read_p*10+read_ca-48,read_ca=getchar();
        return read_p;
    }
    struct na{int y,z,ne,k;}b[200001],B[4000001];
    int n,m,a[200001],x,y,l[200001],num=0,de[200001],L[200001],Num=0,s[200001],Si,ro,ma;
    bool bo[200001];
    long long mmh[200001][5],S[200001][5];
    long long MMH=0;
    inline void in(int x,int y){b[++num].y=y;b[num].ne=l[x];l[x]=num;}
    inline void In(int x,int y,int z,int k){B[++Num].y=y;B[Num].z=z;B[Num].k=k;B[Num].ne=L[x];L[x]=Num;}
    struct tree{int ma,mi;}t[4000001];
    void add(int p,int l,int r,int v){
        if (a[t[p].ma]<a[v]||t[p].ma==0) t[p].ma=v;
        if (a[t[p].mi]>a[v]||t[p].mi==0) t[p].mi=v;
        if (l==r) return;
        int mid=l+r>>1;
        if (a[v]<=mid) add(lp,l,mid,v);else add(rp,mid+1,r,v);
    }
    int quea(int p,int l,int r,int R){
        if (R>=r) return t[p].ma;
        int mid=l+r>>1;
        if (R<=mid) return quea(lp,l,mid,R);else if (mid=quea(rp,mid+1,r,R)) return mid;else return t[lp].ma;
    }
    int quei(int p,int l,int r,int R){
        if (R<=l) return t[p].mi;
        int mid=l+r>>1;
        if (R>mid) return quei(rp,mid+1,r,R);else if (mid=quei(lp,l,mid,R)) return mid;else return t[rp].mi;
    }
    void gs(int x,int f){
        s[x]=1;
        int u=0;
        for (register int i=l[x];i;i=b[i].ne)
        if (b[i].y!=f&&!bo[b[i].y]){
            gs(b[i].y,x);
            s[x]+=s[b[i].y];
            if (u<s[b[i].y]) u=s[b[i].y];
        }
        if (Si-s[x]>u) u=Si-s[x];
        if (u<ma) ma=u,ro=x;
    }
    void dfs(int x,int f,int r,int z,int k){
        s[x]=1;
        In(x,r,z,k);
        for (register int i=l[x];i;i=b[i].ne)
        if (!bo[b[i].y]&&b[i].y!=f) dfs(b[i].y,x,r,z+1,k),s[x]+=s[b[i].y];
    }
    void work(int x,int S){
        Si=S;ma=1e9;gs(x,0);bo[x=ro]=1;
        int u=0;
        for (register int i=l[x];i;i=b[i].ne) if (!bo[b[i].y]) dfs(b[i].y,x,x,1,++u);In(x,x,0,++u);
        for (register int i=l[x];i;i=b[i].ne) if (!bo[b[i].y]) work(b[i].y,s[b[i].y]);
    }
    int main(){
        register int i,j;
        n=read();a[n+1]=n+1;add(1,0,n+1,0);add(1,0,n+1,n+1);
        a[1]=read();add(1,0,n+1,1);de[1]=1;
        for (i=2;i<=n;i++){
            a[i]=read();
            x=quea(1,0,n+1,a[i]-1);y=quei(1,0,n+1,a[i]+1);
            if (de[x]>de[y]){
                in(x,i);
                in(i,x);
                de[i]=de[x]+1;
            }else{
                in(y,i);
                in(i,y);
                de[i]=de[y]+1;
            }
            add(1,0,n+1,i);
        }
        work(1,n);
        for (i=1;i<=n;i++){
            for (j=L[i];j;j=B[j].ne) MMH+=1LL*B[j].z*(S[B[j].y][0]-S[B[j].y][B[j].k])+mmh[B[j].y][0]-mmh[B[j].y][B[j].k],
            mmh[B[j].y][0]+=B[j].z,mmh[B[j].y][B[j].k]+=B[j].z,S[B[j].y][0]++,S[B[j].y][B[j].k]++;
            printf("%lld
    ",MMH);
        }
    }
    View Code
  • 相关阅读:
    在android 5.0以上,如何判断当前应用是在前台还是后台
    Android实现手机摄像头的自动对焦
    抓包获取百度音乐API
    andriod 自定义来电界面功能
    Android 自定义相机
    解决Android拍照保存在系统相册不显示的问题
    有关Color和Drawable你所不知道的那些内容
    Android主题切换方案总结
    设置background属性使用selector的时候内置?attr报错的解决方案
    一步一步解析google camera2 demo(三)
  • 原文地址:https://www.cnblogs.com/Enceladus/p/5764382.html
Copyright © 2011-2022 走看看