关闭

动态树 解题报告

标签: 倍增
467人阅读 评论(0) 收藏 举报
分类:

这个题我做的时候没有考虑到一个性质,导致多了一个log,然后麻烦了好多好多。
就是说合并两个区间的时候,我以为左边的最小值会接管右边第一个比它小的左边的一段,所以我要求这一段的最大值。
但是实际上,如果右边右段的最大值比右边左段的最大值大的话,显然这是无论如何都不能更新答案的,所以我们直接用右边的最大值就好了。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
using namespace std;
#include<algorithm>
#include<cstdlib>
#define inf 1e9
//About read
inline void in(int &x){
    char c=getchar();
    while(c<'0'||c>'9')c=getchar();
    x=0;
    for(;c>='0'&&c<='9';c=getchar())x=x*10+c-'0';
}
int a[200005];
//About tree
int ptr[100005],next[200005],succ[200005],etot=1;
int fa[200005][18],son[200005][18];//[i,i+2^j)
int depth[200005];
struct TS{
    int max,min,ans,revans;
}st[200005][18];
inline void addedge(int u,int v){
    next[etot]=ptr[u],ptr[u]=etot,succ[etot++]=v;
}
inline TS merge(TS a,TS b){
    return (TS){max(a.max,b.max),min(a.min,b.min),max(b.max-a.min,max(a.ans,b.ans)),max(a.max-b.min,max(a.revans,b.revans))};
}
inline void out(TS a){
    cout<<"{"<<a.max<<","<<a.min<<","<<a.ans<<","<<a.revans<<"}";
}
inline void build(int node){
    depth[node]=depth[fa[node][1]]+1;

    fa[node][0]=node;
    for(int i=2;i<18;++i)fa[node][i]=fa[fa[node][i-1]][i-1];

    st[node][0]=(TS){a[node],a[node],0};
    st[node][1]=(TS){max(a[fa[node][1]],a[node]),min(a[fa[node][1]],a[node]),max(a[fa[node][1]]-a[node],0),max(a[node]-a[fa[node][1]],0)};
    for(int i=2;i<18;++i){
        st[node][i]=merge(st[node][i-1],st[fa[node][i-1]][i-1]);
        /*cout<<"Merge:";
        out(st[node][i-1]);
        cout<<"+";
        out(st[fa[node][i-1]][i-1]);
        cout<<"=";
        out(st[node][i]);
        cout<<endl;*/
    }

    for(int i=ptr[node];i;i=next[i])
        if(succ[i]!=fa[node][1]){
            fa[succ[i]][1]=node;
            build(succ[i]);
        }
}
int main(){
    freopen("lct.in","r",stdin);
    freopen("lct.out","w",stdout);
    int n,m,i,j,u,v,s,t,type;
    in(n);
    for(i=1;i<=n;++i)in(a[i]);
    for(i=n;--i;){
        in(u),in(v);
        addedge(u,v),addedge(v,u);
    }
    build(1);
    /*for(i=1;i<=n;++i){
        cout<<"----"<<i<<"-----\n";
        for(j=0;j<18&&fa[i][j];++j){
            cout<<fa[i][j]<<":";
            out(st[i][j]);
            cout<<endl;
        }
    }*/
    in(m);
    int lastans=0,cha;
    TS ans,revans;
    while(m--){
        in(type);
        if(type==1){
            in(s),in(t);
            s^=lastans,t^=lastans;
            revans=st[t][0],ans=st[s][0],cha=abs(depth[s]-depth[t]);
            if(depth[s]>depth[t])//把s往上调 
                for(i=18;--i;)
                    if(depth[fa[s][i]]>=depth[t]){
                        ans=merge(ans,st[s][i]);
                        s=fa[s][i];
                    }
            if(depth[s]<depth[t])//把t往上调 
                for(i=18;--i;)
                    if(depth[fa[t][i]]>=depth[s]){
                        revans=merge(revans,st[t][i]);
                        t=fa[t][i];
                    }
            if(s!=t){
                for(i=18;--i;)
                    if(fa[s][i]!=fa[t][i]){
                        ans=merge(ans,st[s][i]),revans=merge(revans,st[t][i]);
                        s=fa[s][i],t=fa[t][i];
                    }
                ans=merge(ans,st[s][1]);
            }
            lastans=max(revans.max-ans.min,max(ans.ans,revans.revans));
            printf("%d\n",lastans);
        }
        else{
            in(a[++n]),in(fa[n][1]);
            fa[n][1]^=lastans;
            fa[n][0]=n;
            depth[n]=depth[fa[n][1]]+1;
            for(i=2;i<18;++i)fa[n][i]=fa[fa[n][i-1]][i-1];
            st[n][0]=(TS){a[n],a[n],0};
            st[n][1]=(TS){max(a[n],a[fa[n][1]]),min(a[n],a[fa[n][1]]),max(a[fa[n][1]]-a[n],0),max(a[n]-a[fa[n][1]],0)};
            for(i=2;i<18;++i)st[n][i]=merge(st[n][i-1],st[fa[n][i-1]][i-1]);    
        }
    }
}
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:158169次
    • 积分:3449
    • 等级:
    • 排名:第10907名
    • 原创:185篇
    • 转载:1篇
    • 译文:0篇
    • 评论:25条
    最新评论