BZOJ 3999 旅游

Posted on 2016-12-05 16:42  ziliuziliu  阅读(152)  评论(0编辑  收藏  举报

。。。。。。。好长啊。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxv 50050
#define maxe 100500
#define inf 2000000000
using namespace std;
int n,m,val[maxv],x,y,z,g[maxv],nume=1,fath[maxv],top[maxv],w[maxv],fw[maxv],son[maxv],size[maxv],dis[maxv],times=0;
int tot=0,root,ls[maxv<<2],rs[maxv<<2],mn[maxv<<2],mx[maxv<<2],fr[maxv<<2],ba[maxv<<2],lazy[maxv<<2];
int r1,r2,r3;
struct edge
{
    int v,nxt;
}e[maxe];
int read()
{
    char ch;int data=0;
    while (ch<'0' || ch>'9') ch=getchar();
    while (ch>='0' && ch<='9')
    {
        data=data*10+ch-'0';
        ch=getchar();
    }
    return data;
}
void addedge(int u,int v)
{
    e[++nume].v=v;
    e[nume].nxt=g[u];
    g[u]=nume;
}
void dfs1(int x)
{
    size[x]=1;son[x]=0;
    for (int i=g[x];i;i=e[i].nxt)
    {
        int v=e[i].v;
        if (v!=fath[x])
        {
            fath[v]=x;dis[v]=dis[x]+1;
            dfs1(v);
            size[x]+=size[v];
            if (size[son[x]]<size[v]) son[x]=v;
        }
    }
}
void dfs2(int x,int father)
{
      w[x]=++times;fw[times]=x;top[x]=father;
      if (son[x]) dfs2(son[x],father);
      for (int i=g[x];i;i=e[i].nxt)
      {
           int v=e[i].v;
           if ((v!=fath[x]) && (v!=son[x]))
               dfs2(v,v);
      }
}
void reset()
{
    r1=inf;r2=0;r3=0;
}
void pushup(int now)
{
      mx[now]=max(mx[ls[now]],mx[rs[now]]);
      mn[now]=min(mn[ls[now]],mn[rs[now]]);
      fr[now]=max((mx[rs[now]]-mn[ls[now]]),max(fr[ls[now]],fr[rs[now]]));
      ba[now]=max((mx[ls[now]]-mn[rs[now]]),max(ba[ls[now]],ba[rs[now]]));
}
void pushdown(int now,int left,int right)
{
    if (!lazy[now]) return;
    lazy[ls[now]]+=lazy[now];lazy[rs[now]]+=lazy[now];
    mx[ls[now]]+=lazy[now];mx[rs[now]]+=lazy[now];
    mn[ls[now]]+=lazy[now];mn[rs[now]]+=lazy[now];
    lazy[now]=0;
}
void build(int &now,int left,int right)
{
    now=++tot;
    if (left==right) {mn[now]=mx[now]=val[fw[left]];fr[now]=ba[now]=0;return;}
    int mid=(left+right)>>1;
    build(ls[now],left,mid);
    build(rs[now],mid+1,right);
    pushup(now);
}
void ask(int now,int left,int right,int l,int r,int type)
{
    pushdown(now,left,right);
    if ((left==l) && (right==r))
    {
        if (type==1) r3=max(r3,mx[now]-r1);else r3=max(r3,r2-mn[now]);
        if (type==1) r3=max(r3,fr[now]);else r3=max(r3,ba[now]);
        r1=min(r1,mn[now]);r2=max(r2,mx[now]);
        return;
    }
    int mid=(left+right)>>1;
    if (r<=mid) ask(ls[now],left,mid,l,r,type);
    else if (l>=mid+1) ask(rs[now],mid+1,right,l,r,type);
    else
    {
        ask(ls[now],left,mid,l,mid,type);
        ask(rs[now],mid+1,right,mid+1,r,type);
    }
}
void modify(int now,int left,int right,int l,int r,int x)
{
    pushdown(now,left,right);
    if ((left==l) && (right==r))
    {
        lazy[now]+=x;mn[now]+=x;mx[now]+=x;
        return;
    }
    int mid=(left+right)>>1;
    if (r<=mid) modify(ls[now],left,mid,l,r,x);
    else if (l>=mid+1) modify(rs[now],mid+1,right,l,r,x);
    else 
    {
        modify(ls[now],left,mid,l,mid,x);
        modify(rs[now],mid+1,right,mid+1,r,x);
    }
    pushup(now);
}
int lca(int x,int y)
{
    int f1=top[x],f2=top[y];
    while (f1!=f2)
    {
        if (dis[f1]<dis[f2]) {swap(f1,f2);swap(x,y);}
        x=fath[f1];f1=top[x];
    }
    if (dis[x]<dis[y]) return x;else return y;
}
void find_answer(int x,int y,int z)
{
    int ans=0,t=lca(x,y),mn,mx;
    int f1=top[x],f2=top[y];
    mn=inf;mx=0;
    while (f1!=top[t])
    {
          reset();ask(root,1,n,w[f1],w[x],2);
          ans=max(ans,r2-mn);ans=max(ans,r3);mn=min(mn,r1);
         x=fath[f1];f1=top[x];
    }
    reset();ask(root,1,n,w[t],w[x],2);
    ans=max(ans,r2-mn);ans=max(ans,r3);mn=min(mn,r1);
    while (f2!=top[t])
    {
        reset();ask(root,1,n,w[f2],w[y],1);
        ans=max(ans,mx-r1);ans=max(ans,r3);mx=max(mx,r2);
        y=fath[f2];f2=top[y];
    }
    reset();ask(root,1,n,w[t],w[y],1);
    ans=max(ans,mx-r1);ans=max(ans,r3);mx=max(mx,r2);
    ans=max(ans,mx-mn);
    printf("%d\n",ans);
}
void modify_tree(int x,int y,int z)
{
      int f1=top[x],f2=top[y];
      while (f1!=f2)
      {
         if (dis[f1]<dis[f2]) {swap(f1,f2);swap(x,y);}
         modify(root,1,n,w[f1],w[x],z);
         x=fath[f1];f1=top[x];
      }
      if (dis[x]>dis[y]) swap(x,y);
     modify(root,1,n,w[x],w[y],z);
}
int main()
{
     n=read();
     for (int i=1;i<=n;i++) val[i]=read();
    for (int i=1;i<=n-1;i++)
    {
        x=read();y=read();
        addedge(x,y);addedge(y,x);
    }
    dfs1(1);
    dfs2(1,1);
    build(root,1,n);
    m=read();
    for (int i=1;i<=m;i++)
    {
        x=read();y=read();z=read();
        find_answer(x,y,z);
        modify_tree(x,y,z);
    }
    return 0;
}