• 【主席树】【最近公共祖先】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?'
    ':' ');
        }
        }
        return 0;
    }
  • 相关阅读:
    poj2411
    poj2403
    poj2479
    poj2593
    跟着B站UP主小姐姐去华为坂田基地采访扫地僧
    云小课 | 不小心删除了数据库,除了跑路还能咋办?
    GaussDB(for MySQL)如何在存储架构设计上做到高可靠、高可用
    华为侯金龙:打造行业智能体,共建全场景智慧
    华为轮值董事长郭平2020全联接大会主题演讲:永远面向阳光,阴影甩在身后
    【API进阶之路】太秃然了,老板要我一周内检测并导入一万个小时的视频
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/7414590.html
Copyright © 2020-2023  润新知