博客园 首页 私信博主 显示目录 隐藏目录 管理 动画

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\n",MMH);
    }
}
View Code

 

posted @ 2016-08-12 11:50  swm_sxt  阅读(301)  评论(0编辑  收藏  举报