树链剖分

cogs||bzoj1036 树的统计count

题目大意:模板题。

思路:模板题。

#include<iostream>

#include<cstdio>

#define maxnode 30001

#define mid (l+r)/2

#define inf 2100000000LL

using namespace std;

struct use{

    int fa,top,siz,son,dep,tid;

}tree[maxnode]={0};

struct seg{

    int maxn,sum;

}t[maxnode*4]={0};

int point[maxnode*2]={0},next[maxnode*2]={0},en[maxnode*2],tot=0,tt[maxnode],wi[maxnode];

char ch[10];

bool visit[maxnode]={false};

void add(int st,int enn)

{

    ++tot;next[tot]=point[st];point[st]=tot;en[tot]=enn;

    ++tot;next[tot]=point[enn];point[enn]=tot;en[tot]=st;

}

void findc(int u,int fa,int depth)

{

    int i,j,maxsiz=0;

    visit[u]=true;tree[u].siz=1;

    tree[u].fa=fa;tree[u].dep=depth;

    for (i=point[u];i;i=next[i])

      if (!visit[en[i]])

      {

        j=en[i];findc(j,u,depth+1);

        tree[u].siz+=tree[j].siz;

        if (tree[j].siz>maxsiz)

        {

            maxsiz=tree[j].siz;

            tree[u].son=j;

        }

      }

}

void connc(int u,int top)

{

    int i,j;

    visit[u]=false;tree[u].top=top;

    tree[u].tid=++tot;tt[tot]=u;

    if (tree[u].son)

        connc(tree[u].son,top);

    for (i=point[u];i;i=next[i])

      if (visit[en[i]])

      {

        j=en[i];connc(j,j);

      }

}

void updata(int i)

{

    t[i].maxn=max(t[i*2].maxn,t[i*2+1].maxn);

    t[i].sum=t[i*2].sum+t[i*2+1].sum;

}

void build(int i,int l,int r)

{

    if (l==r)

    {

        t[i].maxn=t[i].sum=wi[tt[l]];return;

    }

    build(i*2,l,mid);build(i*2+1,mid+1,r);

    updata(i);

}

void change(int i,int l,int r,int x,int y)

{

    if (l==r)

    {

        t[i].maxn=t[i].sum=y;return;

    }

    if (x<=mid) change(i*2,l,mid,x,y);

    else change(i*2+1,mid+1,r,x,y);

    updata(i);

}

int tmax(int i,int l,int r,int ll,int rr)

{

    int maxn;

    if (ll<=l&&r<=rr) return t[i].maxn;

    maxn=-inf;

    if (ll<=mid) maxn=max(maxn,tmax(i*2,l,mid,ll,rr));

    if (rr>mid) maxn=max(maxn,tmax(i*2+1,mid+1,r,ll,rr));

    return maxn;

}

int tsum(int i,int l,int r,int ll,int rr)

{

    int sum=0;

    if (ll<=l&&r<=rr) return t[i].sum;

    if (ll<=mid) sum+=tsum(i*2,l,mid,ll,rr);

    if (rr>mid) sum+=tsum(i*2+1,mid+1,r,ll,rr);

    return sum;

}

int qmax(int x,int y)

{

    int maxn;

    maxn=-inf;

    while(tree[x].top!=tree[y].top)

    {

        if (tree[tree[x].top].dep<tree[tree[y].top].dep) swap(x,y);

        maxn=max(maxn,tmax(1,1,tot,tree[tree[x].top].tid,tree[x].tid));

        x=tree[tree[x].top].fa;

    }

    if (tree[x].dep<tree[y].dep) swap(x,y);

    maxn=max(maxn,tmax(1,1,tot,tree[y].tid,tree[x].tid));

    return maxn;

}

int qsum(int x,int y)

{

    int sum=0;

    while(tree[x].top!=tree[y].top)

    {

        if (tree[tree[x].top].dep<tree[tree[y].top].dep) swap(x,y);

        sum+=tsum(1,1,tot,tree[tree[x].top].tid,tree[x].tid);

        x=tree[tree[x].top].fa;

    }

    if (tree[x].dep<tree[y].dep) swap(x,y);

    sum+=tsum(1,1,tot,tree[y].tid,tree[x].tid);

    return sum;

}

int main()

{

    freopen("bzoj_1036.in","r",stdin);

    freopen("bzoj_1036.out","w",stdout);

    

    int i,j,n,m,a,b,ans;

    scanf("%d",&n);

    for (i=1;i<n;++i)

    {

        scanf("%d%d",&a,&b);

        add(a,b);

    }

    findc(1,0,1);

    tot=0;connc(1,1);

    for (i=1;i<=n;++i) scanf("%d",&wi[i]);

    build(1,1,tot);

    scanf("%d",&m);

    for (i=1;i<=m;++i)

    {

        scanf("%*c%s",&ch);scanf("%d%d",&a,&b);

        if (ch[0]=='C') change(1,1,tot,tree[a].tid,b);

        else

        {

            if (ch[1]=='M') ans=qmax(a,b);

            else ans=qsum(a,b);

            printf("%d\n",ans);

        }

    }

    

    fclose(stdin);

    fclose(stdout);

}
View Code


cogs 树的维护

题目大意:模板题+区间取反。

思路:取反的时候是纯线段树操作,有很多细节:insert、updata和ask的时候都要考虑delta的取值。

#include<iostream>

#include<cstdio>

#include<cstring>

#define maxnode 10001

#define mid (l+r)/2

#define inf 2100000000

using namespace std;

int point[maxnode]={0},next[maxnode*2]={0},en[maxnode*2],va[maxnode*2],bi[maxnode*2],tt[maxnode]={0},wi[maxnode];

char ch[10];

struct use{

    int maxn,minn,delta,sig;

}t[maxnode*4];

void updata(int i)

{

    t[i].maxn=max((t[i].sig==t[i*2].sig ? t[i*2].maxn : -t[i*2].minn),(t[i].sig==t[i*2+1].sig ? t[i*2+1].maxn : -t[i*2+1].minn));

    t[i].minn=min((t[i].sig==t[i*2].sig ? t[i*2].minn : -t[i*2].maxn),(t[i].sig==t[i*2+1].sig ? t[i*2+1].minn : -t[i*2+1].maxn));

}

void build(int i,int l,int r)

{

    if (l==r)

    {

        t[i].maxn=t[i].minn=wi[tt[l]];

        t[i].delta=t[i].sig=0;return;

    }

    build(i*2,l,mid);build(i*2+1,mid+1,r);

    updata(i);

}

void paint(int i)

{

    t[i].sig=1-t[i].sig;t[i].delta=1-t[i].delta;

}

void pushdown(int i)

{

    if (t[i].delta)

    {

        paint(i*2);paint(i*2+1);

        t[i].delta=0;

    }

}

void tchange(int i,int l,int r,int x,int y)

{

    if (l==r)

    {

        if (t[i].sig) t[i].maxn=t[i].minn=-y;

        else t[i].maxn=t[i].minn=y;

        return;

    }

    pushdown(i);

    if (x<=mid) tchange(i*2,l,mid,x,y);

    else tchange(i*2+1,mid+1,r,x,y);

    updata(i);

}

void tneg(int i,int l,int r,int ll,int rr)

{

    if (ll<=l&&r<=rr)

    {

        paint(i);return;

    }

    pushdown(i);

    if (ll<=mid) tneg(i*2,l,mid,ll,rr);

    if (rr>mid) tneg(i*2+1,mid+1,r,ll,rr);

    updata(i);

}

int tmax(int i,int l,int r,int ll,int rr)

{

    int maxn;

    if (ll<=l&&r<=rr)

    {

        if (t[i].sig) return -t[i].minn;

        else return t[i].maxn;

    }

    maxn=-inf;pushdown(i);

    if (ll<=mid) maxn=max(maxn,tmax(i*2,l,mid,ll,rr));

    if (rr>mid) maxn=max(maxn,tmax(i*2+1,mid+1,r,ll,rr));

    return maxn;

}

struct lp{

    int fa[maxnode],son[maxnode],dep[maxnode],top[maxnode],siz[maxnode],tid[maxnode],edge[maxnode],tot;

    bool visit[maxnode];

    void add(int st,int enn,int vaa,int i)

    {

        ++tot;next[tot]=point[st];point[st]=tot;en[tot]=enn;va[tot]=vaa;bi[tot]=i;

        ++tot;next[tot]=point[enn];point[enn]=tot;en[tot]=st;va[tot]=vaa;bi[tot]=i;

    }

    void dfs1(int u,int ff,int depth,int vaa,int ii)

    {

        int i,j,maxsiz=0;

        visit[u]=true;fa[u]=ff;dep[u]=depth;

        son[u]=0;siz[u]=1;wi[u]=vaa;edge[ii]=u;

        for (i=point[u];i;i=next[i])

          if (!visit[j=en[i]])

          {

              dfs1(j,u,depth+1,va[i],bi[i]);

              siz[u]+=siz[j];

              if (siz[j]>maxsiz)

              {

                  maxsiz=siz[j];son[u]=j;

              }

          }

    }

    void dfs2(int u,int anc)

    {

        int i,j;

        visit[u]=false;top[u]=anc;

        tid[u]=++tot;tt[tot]=u;

        if (son[u]) dfs2(son[u],anc);

        for (i=point[u];i;i=next[i])

          if (visit[j=en[i]]) dfs2(j,j);

    }

    void change(int a,int b)

    {

        a=tid[edge[a]];

        tchange(1,1,tot,a,b);

    }

    void neg(int a,int b)

    {

        while(top[a]!=top[b])

        {

            if (dep[top[a]]<dep[top[b]]) swap(a,b);

            tneg(1,1,tot,tid[top[a]],tid[a]);

            a=fa[top[a]];

        }

        if (dep[a]>dep[b]) swap(a,b);

        if (a!=b) tneg(1,1,tot,tid[son[a]],tid[b]);

    }

    void qmax(int a,int b)

    {

        int maxn;

        maxn=-inf;

        while(top[a]!=top[b])

        {

            if (dep[top[a]]<dep[top[b]]) swap(a,b);

            maxn=max(maxn,tmax(1,1,tot,tid[top[a]],tid[a]));

            a=fa[top[a]];

        }

        if (dep[a]>dep[b]) swap(a,b);

        if (a!=b) maxn=max(maxn,tmax(1,1,tot,tid[son[a]],tid[b]));

        printf("%d\n",maxn);

    }

}tree;

int main()

{

    freopen("maintaintree.in","r",stdin);

    freopen("maintaintree.out","w",stdout);

    

    int n,i,j,a,b,c;

    scanf("%d",&n);tree.tot=0;

    memset(tree.visit,false,sizeof(tree.visit));

    for (i=1;i<n;++i)

    {

        scanf("%d%d%d",&a,&b,&c);

        tree.add(a,b,c,i);

    }

    tree.dfs1(1,0,1,0,0);

    tree.tot=0;tree.dfs2(1,1);

    build(1,1,tree.tot);

    while(scanf("%*c%s",&ch)==1)

    {

        if (ch[0]=='D') break;

        scanf("%d%d",&a,&b);

        if (ch[0]=='C') tree.change(a,b);

        if (ch[0]=='N') tree.neg(a,b);

        if (ch[0]=='Q') tree.qmax(a,b);

    }

    

    fclose(stdin);

    fclose(stdout);

}
View Code

 

bzoj3083 遥远的国度

题目大意:换父亲、改点权、子树最小值。

思路:换父亲是三种情况的分类讨论:我们并不是真的换父亲、重新建树。当前根root,子树的根节点x。1)如果root=x,就查询整棵树;2)如果当lca(root,x)!=x,就查询x的子树;3)如果当lca(root,x)=x,就查询x的儿子中离root最近的那个儿子在整棵树中的补集。

#include<iostream>

#include<cstdio>

#include<cstring>

#include<algorithm>

#define maxnode 100001

#define inf 0x7fffffff

using namespace std;

struct use{

    int delta,minn;

}t[maxnode*4]={0};

int point[maxnode]={0},next[maxnode*2]={0},en[maxnode*2]={0},fy[maxnode]={0},tot=0,id[maxnode]={0};

void updata(int i)

{

    t[i].minn=min(t[i*2].minn,t[i*2+1].minn);

}

void pushdown(int i)

{

    if (t[i].delta)

    {

        t[i*2].minn=t[i*2].delta=t[i].delta;

        t[i*2+1].minn=t[i*2+1].delta=t[i].delta;

        t[i].delta=0;

    }

}

void build(int i,int l,int r)

{

    int mid;

    if (l==r)

    {

        t[i].delta=0;t[i].minn=fy[id[l]];return;

    }

    mid=(l+r)/2;

    build(i*2,l,mid);build(i*2+1,mid+1,r);

    updata(i);

}

void tch(int i,int l,int r,int ll,int rr,int v)

{

    int mid;

    if (ll<=l&&r<=rr)

    {

        t[i].delta=t[i].minn=v;return;

    }

    mid=(l+r)/2;

    pushdown(i);

    if (ll<=mid) tch(i*2,l,mid,ll,rr,v);

    if (rr>mid) tch(i*2+1,mid+1,r,ll,rr,v);

    updata(i);

}

int task(int i,int l,int r,int ll,int rr)

{

    int mid,ans;

    if (ll<=l&&r<=rr) return t[i].minn;

    mid=(l+r)/2;ans=inf;pushdown(i);

    if (ll<=mid) ans=min(ans,task(i*2,l,mid,ll,rr));

    if (rr>mid) ans=min(ans,task(i*2+1,mid+1,r,ll,rr));

    return ans;

}

struct lp{

    int fa[maxnode][20],son[maxnode],dep[maxnode],top[maxnode],siz[maxnode],tid[maxnode],ri[maxnode];

    bool visit[maxnode];

    void add(int st,int enn)

    {

        ++tot;next[tot]=point[st];point[st]=tot;en[tot]=enn;

        ++tot;next[tot]=point[enn];point[enn]=tot;en[tot]=st;

    }

    void dfs1(int u,int ff,int depth)

    {

        int i,j,maxsiz=0;

        visit[u]=true;fa[u][0]=ff;dep[u]=depth;

        son[u]=0;siz[u]=1;

        for (i=1;i<=18;++i) fa[u][i]=fa[fa[u][i-1]][i-1];

        for (i=point[u];i;i=next[i])

        {

            if (!visit[j=en[i]])

            {

                dfs1(j,u,depth+1);

                siz[u]+=siz[j];

                if (siz[j]>maxsiz)

                {

                    maxsiz=siz[j];son[u]=j;

                }

            }

        }

    }

    void dfs2(int u,int anc)

    {

        int i,j;

        visit[u]=false;top[u]=anc;

        tid[u]=++tot;id[tot]=u;

        if (son[u]) dfs2(son[u],anc);

        for (i=point[u];i;i=next[i])

        {

            if (visit[j=en[i]]) dfs2(j,j);

        }

        ri[u]=tot;

    }

    int lca(int a,int b)

    {

        int i,j;

        if (dep[a]>dep[b]) swap(a,b);

        for (i=18;i>=0;--i)

            if (dep[a]<=dep[fa[b][i]]) b=fa[b][i];

        if (a==b) return a;

        for (i=18;i>=0;--i)

        {

            if (fa[a][i]!=fa[b][i])

            {

                a=fa[a][i];b=fa[b][i];

            }

        }

        return fa[a][0];

    }

    void change(int a,int b,int v)

    {

        int i,j;

        while(top[a]!=top[b])

        {

            if (dep[top[a]]<dep[top[b]]) swap(a,b);

            tch(1,1,tot,tid[top[a]],tid[a],v);

            a=fa[top[a]][0];

        }

        if (dep[a]>dep[b]) swap(a,b);

        tch(1,1,tot,tid[a],tid[b],v);

    }

    int ask(int a,int root)

    {

        int ans,ll,i,j;

        if (a==root) return task(1,1,tot,1,tot);

        ll=lca(a,root);

        if (ll!=a) return task(1,1,tot,tid[a],ri[a]);

        else

        {

            ans=inf;j=root;

            for (i=18;i>=0;--i)

                if (dep[fa[j][i]]>dep[a]) j=fa[j][i];

            ans=min((tid[j]>1 ? task(1,1,tot,1,tid[j]-1) : inf),(ri[j]<tot ? task(1,1,tot,ri[j]+1,tot) : inf));

            return ans;

        }

    }

}tree;

int main()

{

    int u,v,n,m,i,j,opt,root,p1,p2,ans;

    scanf("%d%d",&n,&m);

    for (i=1;i<n;++i)

    {

        scanf("%d%d",&u,&v);

        tree.add(u,v);

    }

    for (i=1;i<=n;++i) scanf("%d",&fy[i]);

    scanf("%d",&root);tot=0;

    memset(tree.visit,false,sizeof(tree.visit));

    tree.dfs1(root,0,1);

    tree.dfs2(root,root);

    build(1,1,tot);

    for (i=1;i<=m;++i)

    {

        scanf("%d",&opt);

        if (opt==1) scanf("%d",&root);

        if (opt==2)

        {

            scanf("%d%d%d",&p1,&p2,&v);

            tree.change(p1,p2,v);

        }

        if (opt==3)

        {

            scanf("%d",&p1);

            ans=tree.ask(p1,root);

            printf("%d\n",ans);

        }

    }

}
View Code

 

bzoj2243 染色

题目大意:区间修改、区间不同子段的个数。

思路:线段树上的操作。

#include<iostream>

#include<cstdio>

#include<cstring>

#include<algorithm>

#define maxnode 100001

using namespace std;

struct use{

    int lc,rc,sum,delta;

}t[maxnode*4]={0};

int point[maxnode]={0},next[maxnode*2]={0},en[maxnode*2]={0},id[maxnode]={0},tot=0,fy[maxnode]={0};

void updata(int i)

{

    t[i].lc=t[i*2].lc;t[i].rc=t[i*2+1].rc;

    t[i].sum=t[i*2].sum+t[i*2+1].sum;

    if (t[i*2].rc==t[i*2+1].lc) --t[i].sum;

}

void pushdown(int i)

{

    if (t[i].delta>=0)

    {

        t[i*2].lc=t[i*2].rc=t[i*2].delta=t[i].delta;t[i*2].sum=1;

        t[i*2+1].lc=t[i*2+1].rc=t[i*2+1].delta=t[i].delta;t[i*2+1].sum=1;

        t[i].delta=-1;

    }

}

void build(int i,int l,int r)

{

    int mid;

    if (l==r)

    {

        t[i].lc=t[i].rc=fy[id[l]];t[i].sum=1;t[i].delta=-1;return;

    }

    mid=(l+r)/2;

    build(i*2,l,mid);build(i*2+1,mid+1,r);

    updata(i);t[i].delta=-1;

}

void tch(int i,int l,int r,int ll,int rr,int v)

{

    int mid;

    if (ll<=l&&r<=rr)

    {

        t[i].lc=t[i].rc=t[i].delta=v;t[i].sum=1;return;

    }

    mid=(l+r)/2;pushdown(i);

    if (ll<=mid) tch(i*2,l,mid,ll,rr,v);

    if (rr>mid) tch(i*2+1,mid+1,r,ll,rr,v);

    updata(i);

}

struct use task(int i,int l,int r,int ll,int rr)

{

    int mid,sum=0;

    bool u1=false,u2=false;

    struct use n1,n2,ans;

    if (ll<=l&&r<=rr) return t[i];

    mid=(l+r)/2;pushdown(i);

    if (ll<=mid) {u1=true;n1=task(i*2,l,mid,ll,rr);}

    if (rr>mid) {u2=true;n2=task(i*2+1,mid+1,r,ll,rr);}

    if (u1) ans.lc=n1.lc;

    else ans.lc=n2.lc;

    if (u2) ans.rc=n2.rc;

    else ans.rc=n1.rc;

    ans.sum=(u1 ? n1.sum : 0)+(u2 ? n2.sum : 0);

    if (u1&&u2&&n1.rc==n2.lc) --ans.sum;

    return ans;

}

struct lp{

    int fa[maxnode],dep[maxnode],son[maxnode],siz[maxnode],top[maxnode],tid[maxnode];

    bool visit[maxnode];

    void add(int u,int v)

    {

        ++tot;next[tot]=point[u];point[u]=tot;en[tot]=v;

        ++tot;next[tot]=point[v];point[v]=tot;en[tot]=u;

    }

    void dfs1(int u,int ff,int depth)

    {

        int i,j,maxsiz=0;

        fa[u]=ff;dep[u]=depth;son[u]=0;

        visit[u]=true;siz[u]=1;

        for (i=point[u];i;i=next[i])

        {

            if (!visit[j=en[i]])

            {

                dfs1(j,u,depth+1);

                siz[u]+=siz[j];

                if (siz[j]>maxsiz)

                {

                    maxsiz=siz[j];son[u]=j;

                }

            }

        }

    }

    void dfs2(int u,int anc)

    {

        int i,j;

        tid[u]=++tot;top[u]=anc;

        visit[u]=false;id[tot]=u;

        if (son[u]) dfs2(son[u],anc);

        for (i=point[u];i;i=next[i])

        {

            if (visit[j=en[i]]) dfs2(j,j);

        }

    }

    void change(int a,int b,int v)

    {

        int i;

        while(top[a]!=top[b])

        {

            if (dep[top[a]]<dep[top[b]]) swap(a,b);

            tch(1,1,tot,tid[top[a]],tid[a],v);

            a=fa[top[a]];

        }

        if (dep[a]>dep[b]) swap(a,b);

        tch(1,1,tot,tid[a],tid[b],v);

    }

    int ask(int a,int b)

    {

        int ans=0,co[2],kk=0;

        struct use i;

        co[0]=co[1]=-1;

        while(top[a]!=top[b])

        {

            if (dep[top[a]]<dep[top[b]])

            {

                swap(a,b);kk^=1;

            }

            i=task(1,1,tot,tid[top[a]],tid[a]);

            ans+=i.sum;

            if (co[kk]==i.rc) --ans;

            co[kk]=i.lc;

            a=fa[top[a]];

        }

        if (dep[a]>dep[b])

        {

            swap(a,b);kk^=1;

        }

        i=task(1,1,tot,tid[a],tid[b]);

        ans+=i.sum;

        if (co[kk]==i.lc) --ans;

        co[kk]=i.rc;

        if (co[kk]==co[kk^1]) --ans;

        return ans;

    }

}tree;

int main()

{

    int n,m,i,j,u,v,t;

    char ch;

    scanf("%d%d",&n,&m);

    for (i=1;i<=n;++i) scanf("%d",&fy[i]);

    for (i=1;i<n;++i)

    {

        scanf("%d%d",&u,&v);tree.add(u,v);

    }

    memset(tree.visit,false,sizeof(tree.visit));

    tree.dfs1(1,0,1);tot=0;

    tree.dfs2(1,1);build(1,1,tot);

    for (i=1;i<=m;++i)

    {

        while(scanf("%c",&ch)==1)

        {

            if (ch=='C'||ch=='Q') break;

        }

        if (ch=='C')

        {

            scanf("%d%d%d",&u,&v,&t);

            tree.change(u,v,t);

        }

        else

        {

            scanf("%d%d",&u,&v);

            printf("%d\n",tree.ask(u,v));

        }

    }

}
View Code

 

codevs3305&&3306 水果姐逛水果街系列

题目大意:查询树上从a到b的路径中后面减前面的最大差值(+单点修改)。

思路:链剖+线段树的操作,稍复杂一点,分类讨论。有点像上一题。

#include<iostream>

#include<cstdio>

#include<cstring>

#include<algorithm>

#define maxnode 200001

#define inf 2100000000

using namespace std;

int point[maxnode]={0},next[maxnode*2]={0},en[maxnode*2]={0},fy[maxnode]={0},id[maxnode]={0},tot=0;

struct use{

    int maxn,minn,mac,mic;

}t[maxnode*4];

void updata(int i)

{

    t[i].mac=max(t[i*2].mac,max(t[i*2+1].mac,t[i*2+1].maxn-t[i*2].minn));

    t[i].mic=max(t[i*2].mic,max(t[i*2+1].mic,t[i*2].maxn-t[i*2+1].minn));

    t[i].maxn=max(t[i*2].maxn,t[i*2+1].maxn);

    t[i].minn=min(t[i*2].minn,t[i*2+1].minn);

}

void build(int i,int l,int r)

{

    int mid;

    if (l==r)

    {

        t[i].maxn=t[i].minn=fy[id[l]];t[i].mac=t[i].mic=0;return;

    }

    mid=(l+r)/2;

    build(i*2,l,mid);build(i*2+1,mid+1,r);

    updata(i);

}

void tch(int i,int l,int r,int x,int y)

{

    int mid;

    if (l==r)

    {

        t[i].maxn=t[i].minn=y;t[i].mac=t[i].mic=0;return;

    }

    mid=(l+r)/2;

    if (x<=mid) tch(i*2,l,mid,x,y);

    else tch(i*2+1,mid+1,r,x,y);

    updata(i);

}

struct use task(int i,int l,int r,int ll,int rr)

{

    int mid;

    struct use n1,n2,ans;

    bool u1=false,u2=false;

    if (ll<=l&&r<=rr) return t[i];

    mid=(l+r)/2;

    if (ll<=mid) {u1=true;n1=task(i*2,l,mid,ll,rr);}

    if (rr>mid) {u2=true;n2=task(i*2+1,mid+1,r,ll,rr);}

    ans.maxn=0;ans.minn=inf;ans.mac=ans.mic=0;

    if (u1)

    {

        ans.maxn=max(ans.maxn,n1.maxn);

        ans.minn=min(ans.minn,n1.minn);

        ans.mac=max(ans.mac,n1.mac);

        ans.mic=max(ans.mic,n1.mic);

    }

    if (u2)

    {

        ans.maxn=max(ans.maxn,n2.maxn);

        ans.minn=min(ans.minn,n2.minn);

        ans.mac=max(ans.mac,n2.mac);

        ans.mic=max(ans.mic,n2.mic);

    }

    if (u1&&u2)

    {

        ans.mac=max(ans.mac,n2.maxn-n1.minn);

        ans.mic=max(ans.mic,n1.maxn-n2.minn);

    }

    return ans;

}

struct lp{

    int fa[maxnode],dep[maxnode],top[maxnode],tid[maxnode],son[maxnode],siz[maxnode];

    bool visit[maxnode];

    void add(int u,int v)

    {

        ++tot;next[tot]=point[u];point[u]=tot;en[tot]=v;

        ++tot;next[tot]=point[v];point[v]=tot;en[tot]=u;

    }

    void dfs1(int u,int ff,int depth)

    {

        int i,j,maxsiz=0;

        fa[u]=ff;dep[u]=depth;visit[u]=true;

        son[u]=0;siz[u]=1;

        for (i=point[u];i;i=next[i])

        {

            if (!visit[j=en[i]])

            {

                dfs1(j,u,depth+1);

                siz[u]+=siz[j];

                if (siz[j]>maxsiz)

                {

                    maxsiz=siz[j];son[u]=j;

                }

            }

        }

    }

    void dfs2(int u,int anc)

    {

        int i,j;

        top[u]=anc;tid[u]=++tot;

        id[tot]=u;visit[u]=false;

        if (son[u]) dfs2(son[u],anc);

        for (i=point[u];i;i=next[i])

            if (visit[j=en[i]]) dfs2(j,j);

    }

    int ask(int a,int b)

    {

        int j,ans=0,kk=0;

        struct use mo[2],i;

        mo[0].maxn=mo[1].maxn=0;mo[0].minn=mo[1].minn=inf;

        mo[0].mac=mo[1].mac=mo[0].mic=mo[1].mic=0;

        while(top[a]!=top[b])

        {

            if (dep[top[a]]<dep[top[b]])

            {

                swap(a,b);kk^=1;

            }

            i=task(1,1,tot,tid[top[a]],tid[a]);

            if (!kk)

            {

                ans=max(ans,max(i.mic,i.maxn-mo[kk].minn));

                mo[kk].minn=min(mo[kk].minn,i.minn);

                mo[kk].maxn=max(mo[kk].maxn,i.maxn);

            }

            else

            {

                ans=max(ans,max(i.mac,mo[kk].maxn-i.minn));

                mo[kk].minn=min(mo[kk].minn,i.minn);

                mo[kk].maxn=max(mo[kk].maxn,i.maxn);

            }

            a=fa[top[a]];

        }

        if (dep[a]>dep[b])

        {

            swap(a,b);kk^=1;

        }

        i=task(1,1,tot,tid[a],tid[b]);

        if (!kk)

        {

            ans=max(ans,max(i.mac,i.maxn-mo[kk].minn));

            mo[kk].maxn=max(mo[kk].maxn,i.maxn);

            mo[kk].minn=min(mo[kk].minn,i.minn);

            ans=max(ans,mo[kk^1].maxn-mo[kk].minn);

        }

        else

        {

            ans=max(ans,max(i.mic,mo[kk].maxn-i.minn));

            mo[kk].maxn=max(mo[kk].maxn,i.maxn);

            mo[kk].minn=min(mo[kk].minn,i.minn);

            ans=max(ans,mo[kk].maxn-mo[kk^1].minn);

        }

        return ans;

    }

}tree;

int main()

{

    int n,m,i,j,x,y,u,v;

    scanf("%d",&n);

    for (i=1;i<=n;++i) scanf("%d",&fy[i]);

    for (i=1;i<n;++i)

    {

        scanf("%d%d",&u,&v);

        tree.add(u,v);

    }

    memset(tree.visit,false,sizeof(tree.visit));

    tree.dfs1(1,0,1);tot=0;

    tree.dfs2(1,1);scanf("%d",&m);

    build(1,1,tot);

    for (i=1;i<=m;++i)

    {

        scanf("%d%d",&x,&y);

        printf("%d\n",tree.ask(x,y));

    }

}
无修改
#include<iostream>

#include<cstdio>

#include<cstring>

#include<algorithm>

#define maxnode 200001

#define inf 2100000000

using namespace std;

int point[maxnode]={0},next[maxnode*2]={0},en[maxnode*2]={0},fy[maxnode]={0},id[maxnode]={0},tot=0;

struct use{

    int maxn,minn,mac,mic;

}t[maxnode*4];

void updata(int i)

{

    t[i].mac=max(t[i*2].mac,max(t[i*2+1].mac,t[i*2+1].maxn-t[i*2].minn));

    t[i].mic=max(t[i*2].mic,max(t[i*2+1].mic,t[i*2].maxn-t[i*2+1].minn));

    t[i].maxn=max(t[i*2].maxn,t[i*2+1].maxn);

    t[i].minn=min(t[i*2].minn,t[i*2+1].minn);

}

void build(int i,int l,int r)

{

    int mid;

    if (l==r)

    {

        t[i].maxn=t[i].minn=fy[id[l]];t[i].mac=t[i].mic=0;return;

    }

    mid=(l+r)/2;

    build(i*2,l,mid);build(i*2+1,mid+1,r);

    updata(i);

}

void tch(int i,int l,int r,int x,int y)

{

    int mid;

    if (l==r)

    {

        t[i].maxn=t[i].minn=y;t[i].mac=t[i].mic=0;return;

    }

    mid=(l+r)/2;

    if (x<=mid) tch(i*2,l,mid,x,y);

    else tch(i*2+1,mid+1,r,x,y);

    updata(i);

}

struct use task(int i,int l,int r,int ll,int rr)

{

    int mid;

    struct use n1,n2,ans;

    bool u1=false,u2=false;

    if (ll<=l&&r<=rr) return t[i];

    mid=(l+r)/2;

    if (ll<=mid) {u1=true;n1=task(i*2,l,mid,ll,rr);}

    if (rr>mid) {u2=true;n2=task(i*2+1,mid+1,r,ll,rr);}

    ans.maxn=0;ans.minn=inf;ans.mac=ans.mic=0;

    if (u1)

    {

        ans.maxn=max(ans.maxn,n1.maxn);

        ans.minn=min(ans.minn,n1.minn);

        ans.mac=max(ans.mac,n1.mac);

        ans.mic=max(ans.mic,n1.mic);

    }

    if (u2)

    {

        ans.maxn=max(ans.maxn,n2.maxn);

        ans.minn=min(ans.minn,n2.minn);

        ans.mac=max(ans.mac,n2.mac);

        ans.mic=max(ans.mic,n2.mic);

    }

    if (u1&&u2)

    {

        ans.mac=max(ans.mac,n2.maxn-n1.minn);

        ans.mic=max(ans.mic,n1.maxn-n2.minn);

    }

    return ans;

}

struct lp{

    int fa[maxnode],dep[maxnode],top[maxnode],tid[maxnode],son[maxnode],siz[maxnode];

    bool visit[maxnode];

    void add(int u,int v)

    {

        ++tot;next[tot]=point[u];point[u]=tot;en[tot]=v;

        ++tot;next[tot]=point[v];point[v]=tot;en[tot]=u;

    }

    void dfs1(int u,int ff,int depth)

    {

        int i,j,maxsiz=0;

        fa[u]=ff;dep[u]=depth;visit[u]=true;

        son[u]=0;siz[u]=1;

        for (i=point[u];i;i=next[i])

        {

            if (!visit[j=en[i]])

            {

                dfs1(j,u,depth+1);

                siz[u]+=siz[j];

                if (siz[j]>maxsiz)

                {

                    maxsiz=siz[j];son[u]=j;

                }

            }

        }

    }

    void dfs2(int u,int anc)

    {

        int i,j;

        top[u]=anc;tid[u]=++tot;

        id[tot]=u;visit[u]=false;

        if (son[u]) dfs2(son[u],anc);

        for (i=point[u];i;i=next[i])

            if (visit[j=en[i]]) dfs2(j,j);

    }

    int ask(int a,int b)

    {

        int j,ans=0,kk=0;

        struct use mo[2],i;

        mo[0].maxn=mo[1].maxn=0;mo[0].minn=mo[1].minn=inf;

        mo[0].mac=mo[1].mac=mo[0].mic=mo[1].mic=0;

        while(top[a]!=top[b])

        {

            if (dep[top[a]]<dep[top[b]])

            {

                swap(a,b);kk^=1;

            }

            i=task(1,1,tot,tid[top[a]],tid[a]);

            if (!kk)

            {

                ans=max(ans,max(i.mic,i.maxn-mo[kk].minn));

                mo[kk].minn=min(mo[kk].minn,i.minn);

                mo[kk].maxn=max(mo[kk].maxn,i.maxn);

            }

            else

            {

                ans=max(ans,max(i.mac,mo[kk].maxn-i.minn));

                mo[kk].minn=min(mo[kk].minn,i.minn);

                mo[kk].maxn=max(mo[kk].maxn,i.maxn);

            }

            a=fa[top[a]];

        }

        if (dep[a]>dep[b])

        {

            swap(a,b);kk^=1;

        }

        i=task(1,1,tot,tid[a],tid[b]);

        if (!kk)

        {

            ans=max(ans,max(i.mac,i.maxn-mo[kk].minn));

            mo[kk].maxn=max(mo[kk].maxn,i.maxn);

            mo[kk].minn=min(mo[kk].minn,i.minn);

            ans=max(ans,mo[kk^1].maxn-mo[kk].minn);

        }

        else

        {

            ans=max(ans,max(i.mic,mo[kk].maxn-i.minn));

            mo[kk].maxn=max(mo[kk].maxn,i.maxn);

            mo[kk].minn=min(mo[kk].minn,i.minn);

            ans=max(ans,mo[kk].maxn-mo[kk^1].minn);

        }

        return ans;

    }

}tree;

int main()

{

    int n,m,i,j,x,y,u,v;

    scanf("%d",&n);

    for (i=1;i<=n;++i) scanf("%d",&fy[i]);

    for (i=1;i<n;++i)

    {

        scanf("%d%d",&u,&v);

        tree.add(u,v);

    }

    memset(tree.visit,false,sizeof(tree.visit));

    tree.dfs1(1,0,1);tot=0;

    tree.dfs2(1,1);scanf("%d",&m);

    build(1,1,tot);

    for (i=1;i<=m;++i)

    {

        scanf("%d%d%d",&j,&x,&y);

        if (j==0) tch(1,1,tot,tree.tid[x],y);

        else printf("%d\n",tree.ask(x,y));

    }

}
有修改

 

你可能感兴趣的:(树)