【主席树】【最近公共祖先】hdu6162 Ch’s gift

 题意:一棵树,每个点有个权值,m次询问,每次给你一条链和两个值a,b,问你这条链上权值在[a,b]之间的权值的和是多少。
std竟然是2个log的……完全没必要链剖,每个结点的主席树从其父节点转移过来,这样每个结点的主席树存储的就是它到根点的权值。
然后链询问,直接在主席树上作差,T[u]+T[v]-T[lca(u,v)]-T[fa(lca(u,v))]即可。只有一个log。
当然要先离散化。
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define N 300005
typedef long long ll;
int v[N<<1],first[N],nex[N<<1],en;
void AddEdge(int U,int V)
{
    v[++en]=V;
    nex[en]=first[U];
    first[U]=en;
}
struct Point{int v,p;}t[N];
bool operator < (Point a,Point b){return a.v<b.v;}
int n,m,ma[N],a[N],zy;
struct Node{ll v;int lc,rc;}T[100005*27];
int root[N],e=1;
void BuildTree(int cur,int l,int r)
{
    if(l==r) return;
    int m=(l+r>>1);
    T[cur].lc=++e;
    BuildTree(T[cur].lc,l,m);
    T[cur].rc=++e;
    BuildTree(T[cur].rc,m+1,r);
}
void Insert(int pre,int cur,int p,int v,int l,int r)
{
    if(l==r)
      {
        T[cur].v=T[pre].v+(ll)v;
        return;
      }
    int m=(l+r>>1);
    if(p<=m)
      {
        T[cur].lc=++e;
        T[cur].rc=T[pre].rc;
        Insert(T[pre].lc,T[cur].lc,p,v,l,m);
      }
    else
      {
        T[cur].rc=++e;
        T[cur].lc=T[pre].lc;
        Insert(T[pre].rc,T[cur].rc,p,v,m+1,r);
      }
    T[cur].v=T[T[cur].lc].v+T[T[cur].rc].v;
}
int top[N],siz[N],son[N],fa[N],dep[N];
void df1(int U)
{
    siz[U]=1;
    for(int i=first[U];i;i=nex[i])
      if(v[i]!=fa[U])
        {
          fa[v[i]]=U;
          dep[v[i]]=dep[U]+1;
          df1(v[i]);
          siz[U]+=siz[v[i]];
          if(siz[v[i]]>siz[son[U]])
            son[U]=v[i];
        }
}
void df2(int U)
{
    if(son[U])
      {
        top[son[U]]=top[U];
        df2(son[U]);
      }
    for(int i=first[U];i;i=nex[i])
      if(v[i]!=fa[U]&&v[i]!=son[U])
        {
          top[v[i]]=v[i];
          df2(v[i]);
        }
}
int lca(int U,int V)
{
    while(top[U]!=top[V])
      {
        if(dep[top[U]]<dep[top[V]])
          swap(U,V);
        U=fa[top[U]];
      }
    if(dep[U]>dep[V])
      swap(U,V);
    return U;
}
void dfs(int U)
{
    root[U]=++e;
    Insert(root[fa[U]],root[U],a[U],ma[a[U]],1,zy);
    for(int i=first[U];i;i=nex[i])
      if(v[i]!=fa[U])
        dfs(v[i]);
}
ll query(int ql,int qr,int LCA,int FLCA,int A,int B,int l,int r)
{
    if(A<=l && r<=B){
        return T[ql].v+T[qr].v-T[LCA].v-T[FLCA].v;
    }
    int m=(l+r>>1);
    ll res=0;
    if(A<=m)
      res+=query(T[ql].lc,T[qr].lc,T[LCA].lc,T[FLCA].lc,A,B,l,m);
    if(m<B)
      res+=query(T[ql].rc,T[qr].rc,T[LCA].rc,T[FLCA].rc,A,B,m+1,r);
    return res;
}
int xs[N],ys[N],as[N],bs[N];
int main()
{
    //freopen("b.in","r",stdin);
    //freopen("b.out","w",stdout);
    int X,Y,W;
    while(scanf("%d%d",&n,&m)!=EOF){
        e=0;
        zy=0;
        en=0;
        memset(first,0,sizeof(first));
        memset(a,0,sizeof(a));
        memset(ma,0,sizeof(ma));
        memset(t,0,sizeof(t));
        memset(T,0,sizeof(T));
        memset(root,0,sizeof(root));
        memset(top,0,sizeof(top));
        memset(son,0,sizeof(son));
        memset(siz,0,sizeof(siz));
        memset(fa,0,sizeof(fa));
        memset(dep,0,sizeof(dep));
        for(int i=1;i<=n;++i)
      {
        scanf("%d",&t[i].v);
        t[i].p=i;
      }
    for(int i=1;i<n;++i)
      {
        scanf("%d%d",&X,&Y);
        AddEdge(X,Y);
        AddEdge(Y,X);
      }
    int all=n;
    for(int i=1;i<=m;++i){
        scanf("%d%d%d%d",&xs[i],&ys[i],&as[i],&bs[i]);
        t[++all].v=as[i];
        t[all].p=all;
        t[++all].v=bs[i];
        t[all].p=all;
    }
    sort(t+1,t+all+1);
    if(t[1].p<=n){
        a[t[1].p]=++zy;
    }
    else{
        if((t[1].p-n)%2==1){
            as[(t[1].p-n-1)/2+1]=++zy;
        }
        else{
            bs[(t[1].p-n)/2]=++zy;
        }
    }
    ma[zy]=t[1].v;
    for(int i=2;i<=all;++i){
        if(t[i].v!=t[i-1].v) ++zy;
        if(t[i].p<=n){
            a[t[i].p]=zy;
        }
        else{
            if((t[i].p-n)%2==1){
                as[(t[i].p-n-1)/2+1]=zy;
            }
            else{
                bs[(t[i].p-n)/2]=zy;
            }
        }
        ma[zy]=t[i].v;
    }
    root[0]=1;
    BuildTree(root[0],1,zy);
    df1(1);
    top[1]=1;
    df2(1);
    dfs(1);
    for(int i=1;i<=m;++i){
        X=xs[i];
        Y=ys[i];
        int t=lca(X,Y);
        printf("%lld%c",query(root[X],root[Y],root[t],root[fa[t]],as[i],bs[i],1,zy),i==m?'\n':' ');
    }
    }
    return 0;
}
posted @ 2017-08-23 00:20  AutSky_JadeK  阅读(145)  评论(0)    收藏  举报
TVアニメ「Charlotte(シャーロット)」公式サイト TVアニメ「Charlotte(シャーロット)」公式サイト