zoukankan      html  css  js  c++  java
  • [LNOI2014]LCA(树链剖分)

    [LNOI2014]LCA(树链剖分)

    BZOJ传送门

    Luogu传送门

    题目:给你一棵树,给你n个询问,每个询问要求输出$sum_{i=l}^{r}depth(LCA(i,z))$

    细看看其实没有想象的那么难

    大体思路:

    1、对于每个询问,考虑打差分变成$sum_{i=0}^{r}depth(LCA(i,z))-sum_{i=0}^{l-1}depth(LCA(i,z))$

    2、那么这里就是一个思考点了

    如何表示$sum_{i=0}^{p}depth(LCA(i,z))$?

    我也不知道

    这种时候就该换一个角度思考了

    啥是深度?

    不就是从根到他有几个点嘛

    对于两个点i,j

    从i向根的路径上+1

    那么$query(root,j)$就是要求的$dep(LCA(i,j))$了

    到这里思路就差不多出来了

    ①把每个询问分成两个,打差分

    ②排序询问,逐个插入$add(i,root,1)$

    ③每个询问查出$query(z,root)$

    好了答案出来了

    #include<cstdio>
    #include<algorithm>
    using std::sort;
    #define mo 201314
    void MOD(int &a){a=(a+mo*2)%mo;}
    int n,m;
    struct sumireko
    {
        int to,ne;
    }e[100011];
    int he[50011],ecnt;
    void addline(int f,int t)
    {
        e[++ecnt].to=t;
        e[ecnt].ne=he[f];
        he[f]=ecnt;
    }
    
    int fa[50011],hop[50011],size[50011],dson[50011],llen[50011],dep[50011],idn[50011],idnar;
    void dfs1(int x)
    {
        size[x]=1;
        int lin=-1;
        for(int i=he[x],t;i;i=e[i].ne)
        {
            t=e[i].to;
            dfs1(t);
            size[x]+=size[t];
            if(lin<size[t])
            {
                lin=size[t];
                dson[x]=t;
            }
        }
    }
    
    void dfs2(int x,int top)
    {
        idn[x]=++idnar;
        hop[x]=top;
        llen[top]++;
        if(!dson[x]) return;
        dfs2(dson[x],top);
        for(int i=he[x],t;i;i=e[i].ne)
        {
            t=e[i].to;
            if(t==dson[x]) continue;
            dfs2(t,t);
        }
    }
    
    struct usami
    {
        int f,id,r,z;
        void set(int u,int i,int o,int p){f=u,id=i,r=o,z=p;}
        bool friend operator < (usami a,usami b)
        {
            return a.r<b.r;
        }
    }qqq[100011];
    int qcnt;
    
    int ans[50011];
    
    struct segtree
    {
        int v[200011],del[200011],size[200011];
        void build(int px,int pl,int pr)
        {
            if(pl==pr)
            {
                size[px]=1;
                return;
            }
            int mid=(pl+pr)>>1;
            build(px<<1,pl,mid);
            build(px<<1|1,mid+1,pr);
            size[px]=size[px<<1]+size[px<<1|1];
        }
        void fuckup(int px,int pl,int pr)
        {
            if(pl==pr) return;
            v[px]=v[px<<1]+v[px<<1|1];
            MOD(v[px]);
        }
        void fuckdown(int px,int pl,int pr)
        {
            if(pl==pr) return;
            if(del[px])
            {
                v[px<<1]+=del[px]*size[px<<1];MOD(v[px<<1]);
                del[px<<1]+=del[px];MOD(del[px<<1]);
                v[px<<1|1]+=del[px]*size[px<<1|1];MOD(v[px<<1|1]);
                del[px<<1|1]+=del[px];MOD(del[px<<1|1]);
                del[px]=0;
            }
        }
        void add(int px,int pl,int pr,int vin,int ql,int qr)
        {
            if(ql<=pl&&qr>=pr)
            {
                v[px]+=vin*size[px];
                del[px]+=vin;
                MOD(v[px]);
                MOD(del[px]);
                return;
            }
            fuckdown(px,pl,pr);
            int mid=(pl+pr)>>1;
            if(ql<=mid) add(px<<1,pl,mid,vin,ql,qr);
            if(qr>mid) add(px<<1|1,mid+1,pr,vin,ql,qr);
            fuckup(px,pl,pr);
        }
        int query(int px,int pl,int pr,int ql,int qr)
        {
            if(ql<=pl&&qr>=pr) return v[px];
            fuckdown(px,pl,pr);
            int mid=(pl+pr)>>1;
            int ret=0;
            if(ql<=mid) ret+=query(px<<1,pl,mid,ql,qr),MOD(ret);
            if(qr>mid) ret+=query(px<<1|1,mid+1,pr,ql,qr),MOD(ret);
            return ret; 
        }
    }tr;
    
    void inp(int x)
    {
        while(hop[x]!=hop[0])
        {
            tr.add(1,1,n,1,idn[hop[x]],idn[x]);
            x=fa[hop[x]];
        }
        tr.add(1,1,n,1,idn[0],idn[x]);
    }
    
    void qq(int x,int id,int f)
    {
        int prt=0;
        while(hop[x]!=hop[0])
        {
            prt+=tr.query(1,1,n,idn[hop[x]],idn[x]);
            MOD(prt);
            x=fa[hop[x]];
        }
        prt+=tr.query(1,1,n,idn[0],idn[x]);
        MOD(prt);
        ans[id]+=f*prt;
        MOD(ans[id]);
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<n;i++) scanf("%d",&fa[i]),addline(fa[i],i);
        dep[0]=1;
        dfs1(0);
        dfs2(0,0);
        tr.build(1,1,n);
        for(int i=1,lin,rin,zin;i<=m;i++)
        {
            scanf("%d%d%d",&lin,&rin,&zin);
            qqq[++qcnt].set(-1,i,lin-1,zin);
            qqq[++qcnt].set(1,i,rin,zin);
        }
        sort(qqq+1,qqq+qcnt+1);
        int tinar=-1;
        for(int i=1;i<=qcnt;i++)
        {
            while(tinar<qqq[i].r) {tinar++;inp(tinar);}
            qq(qqq[i].z,qqq[i].id,qqq[i].f);
        }
        for(int i=1;i<=m;i++)
        printf("%d
    ",ans[i]);
        return 0;
    }
    精污代码慎入
  • 相关阅读:
    【并行计算-CUDA开发】CUDA shared memory bank 冲突
    【并行计算-CUDA开发】CUDA shared memory bank 冲突
    【并行计算-CUDA开发】CUDA bank conflict in shared memory
    【并行计算-CUDA开发】CUDA bank conflict in shared memory
    【并行计算-CUDA开发】从熟悉到精通 英伟达显卡选购指南
    【并行计算-CUDA开发】从熟悉到精通 英伟达显卡选购指南
    【C/C++开发】【VS开发】win32位与x64位下各类型长度对比
    【C/C++开发】【VS开发】win32位与x64位下各类型长度对比
    【并行计算-CUDA开发】浅谈GPU并行计算新趋势
    【并行计算-CUDA开发】浅谈GPU并行计算新趋势
  • 原文地址:https://www.cnblogs.com/rikurika/p/10461831.html
Copyright © 2011-2022 走看看