NOIP模拟赛20191012 T3 垃圾分类【平衡树】

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/C20181220_xiang_m_y/article/details/102555069

题目描述:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

题目分析:

在这里插入图片描述

太久没写平衡树了,照着题解都打了3h+。。。
打完发现还挺棒棒哒。。。颈椎不疼了,手不酸了,一口气打Treap都不喘气儿了。。。

存个代码作纪念。
Code:

#include<bits/stdc++.h>
#define maxn 100005
#define LL long long
using namespace std;
const LL inf = -1ll<<60;
int n,r,a[maxn],fa[maxn],dep[maxn],dod[maxn],top[maxn],son[maxn],siz[maxn];
int fir[maxn],nxt[maxn<<1],to[maxn<<1],tot;
inline void line(int x,int y){nxt[++tot]=fir[x],fir[x]=tot,to[tot]=y;}
void dfs1(int u,int ff){
    dep[u]=dep[fa[u]=ff]+1,siz[u]=1;//avoid rename...
    for(int i=fir[u],v;i;i=nxt[i]) if((v=to[i])!=ff){
        dfs1(v,u),siz[u]+=siz[v];
        if(siz[v]>siz[son[u]]) son[u]=v;
    }
}
void dfs2(int u,int tp){
    top[u]=tp,dod[u]=dep[u];
    if(son[u]) dfs2(son[u],tp),dod[u]=dod[son[u]];
    for(int i=fir[u];i;i=nxt[i]) if(!top[to[i]]) dfs2(to[i],to[i]);
}
int rt[maxn],ch[maxn][2],rnd[maxn],tag[maxn],d[maxn];
LL t[maxn],mx[maxn];
inline void upd(int i){mx[i]=max(t[i]-d[i],max(mx[ch[i][0]],mx[ch[i][1]]));}
inline void pushdown(int i){
    if(tag[i]){
        static int x,now; now=tag[i],tag[i]=0;
        x=ch[i][0],d[x]+=now,tag[x]+=now,mx[x]-=now;
        x=ch[i][1],d[x]+=now,tag[x]+=now,mx[x]-=now;
    }
}
void rot(int &x,int c){
    int y=ch[x][c];
    ch[x][c]=ch[y][!c],ch[y][!c]=x;
    upd(x),upd(y),x=y;
}
void insert(int &i,int x){
    if(!i) {i=x;return;}
    if(d[x]==d[i]) {if(t[x]>t[i]) t[i]=t[x],upd(i);return;}
    pushdown(i);
    int c=d[x]>d[i];
    insert(ch[i][c],x),upd(i);
    if(rnd[i]<rnd[ch[i][c]]) rot(i,c);
}
inline void Addnode(int &i,int x,LL tt,int dd){
    ch[x][0]=ch[x][1]=tag[x]=0;
    t[x]=tt,d[x]=dd,mx[x]=tt-dd,rnd[x]=rand()<<15^rand();
    insert(i,x);
}
void modify(int i,int l,int r,int x,int y){
    if(!i) return;
    if(x<=l&&r<=y) {d[i]--,tag[i]--,mx[i]++;return;}
    pushdown(i);
    if(x<d[i]) modify(ch[i][0],l,d[i]-1,x,y);
    if(y>d[i]) modify(ch[i][1],d[i]+1,r,x,y);
    if(x<=d[i]&&d[i]<=y) d[i]--;
    upd(i);
}
LL query(int i,int l,int r,int x,int y){
    if(!i) return 0;
    if(x<=l&&r<=y) return mx[i];
    pushdown(i); LL ret=0;
    if(x<d[i]) ret=max(ret,query(ch[i][0],l,d[i]-1,x,y));
    if(y>d[i]) ret=max(ret,query(ch[i][1],d[i]+1,r,x,y));
    if(x<=d[i]&&d[i]<=y) ret=max(ret,t[i]-d[i]);
    return ret;
}
int del(int &i,int v){
    if(!i) return 0;
    pushdown(i);//FFFF!!!!!!!!!!
    if(d[i]==v){
        if(!ch[i][0]||!ch[i][1]) {int j=i;i=ch[i][0]+ch[i][1];return j;}
        static int c; rot(i,c=rnd[ch[i][1]]>rnd[ch[i][0]]);
        return del(ch[i][!c],v);
    }
    else if(v<d[i]) return del(ch[i][0],v);
    else return del(ch[i][1],v);
}
LL solve(int u){
    LL ret=0;
    for(int v;u;u=fa[v]) v=top[u],ret=max(ret,query(rt[v],dep[v],dod[v],dep[v],dep[u]));
    return ret;
}
void modify(int u){
    int pre=0,now;
    for(int v;u;u=fa[v],pre=now){
        v=top[u];
        now=del(rt[v],dep[v]);
        modify(rt[v],dep[v],dod[v],dep[v],dep[u]);
        if(pre) Addnode(rt[v],pre,t[pre],d[pre]-1);
    }
    Addnode(rt[r],pre,t[pre]+1,1);
}
int main()
{
    scanf("%d%d",&n,&r);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1,x,y;i<n;i++) scanf("%d%d",&x,&y),line(x,y),line(y,x);
    dfs1(r,0),dfs2(r,r);
    Addnode(rt[r],n+1,1,dep[r]);
    LL ans=0,ret;
    for(int i=1;i<=n;i++){
        ans=max(ans,ret=solve(i)+dep[i]+a[i]);
        modify(i),Addnode(rt[top[i]],i,ret+1,dep[i]);
    }
    printf("%lld\n",ans);
}

猜你喜欢

转载自blog.csdn.net/C20181220_xiang_m_y/article/details/102555069