zoukankan      html  css  js  c++  java
  • BZOJ3626 神思路的树链剖分+线段树维护

    给清华爷的思路跪了 想了N久  觉得可以深度建树开二维的来维护标记...然而N->50000数组存不下  看了别人的题解....原来可以用线段树离线操作对于这个点的深度贡献对于经过的每个节点+1 类似于前缀和的操作 然后对于操作离散化(嗯 最关键的操作就是把深度贡献 均分给他经过的节点上....至于为什么 可以手动画一画  然后想明白这个就发现只是树剖的基本操作 进行区间更新和区间查询即可

    3626: [LNOI2014]LCA

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 3482  Solved: 1365
    [Submit][Status][Discuss]

    Description

    给出一个n个节点的有根树(编号为0到n-1,根节点为0)。一个点的深度定义为这个节点到根的距离+1。
    设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先。
    有q次询问,每次询问给出l r z,求sigma_{l<=i<=r}dep[LCA(i,z)]。
    (即,求在[l,r]区间内的每个节点i与z的最近公共祖先的深度之和)

    Input

    第一行2个整数n q。
    接下来n-1行,分别表示点1到点n-1的父节点编号。
    接下来q行,每行3个整数l r z。

    Output

    输出q行,每行表示一个询问的答案。每个答案对201314取模输出

    Sample Input

    5 2
    0
    0
    1
    1
    1 4 3
    1 4 2

    Sample Output

    8
    5
    /**************************************************************
        Problem: 3626
        User: wang9897
        Language: C++
        Result: Accepted
        Time:2288 ms
        Memory:8776 kb
    ****************************************************************/
     
    #include <bits/stdc++.h>
    #define N 50005
    #define lth 201314
    using namespace std;
    int son[N],num[N],fa[N],dep[N];
    int p[N],fp[N],tp[N],cnt,n,q;
    vector<int>vec[N];
    int read(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return f*x;
    }
    void dfs1(int v,int pre,int deep){
        num[v]=1;fa[v]=pre;dep[v]=deep+1;
        for(int i=0;i<vec[v].size();i++){
            if(vec[v][i]!=pre){
                dfs1(vec[v][i],v,deep+1);
                num[v]+=num[vec[v][i]];
                if(son[v]==-1||num[vec[v][i]]>num[son[v]]){
                    son[v]=vec[v][i];
                }
            }
        }
    }
    void dfs2(int v,int td){
        p[v]=++cnt;fp[cnt]=v;tp[v]=td;
        if(son[v]!=-1) dfs2(son[v],td);
        for(int i=0;i<vec[v].size();i++){
            if(vec[v][i]!=fa[v]&&vec[v][i]!=son[v]) dfs2(vec[v][i],vec[v][i]);
        }
    }
    typedef struct node{
        int l,r,sum,flag;
    }node;
    node d[N<<2];
    void push(int x){
        if(d[x].flag){
            d[x<<1].sum=(d[x<<1].sum+(1ll*d[x].flag*(d[x<<1].r-d[x<<1].l+1))%lth)%lth;d[x<<1|1].sum=(d[x<<1|1].sum+(1ll*d[x].flag*(d[x<<1|1].r-d[x<<1|1].l+1))%lth)%lth;
            d[x<<1].flag=(d[x<<1].flag+d[x].flag)%lth;d[x<<1|1].flag=(d[x<<1|1].flag+d[x].flag)%lth;
            d[x].flag=0;
        }
    }
    void up(int x){
        d[x].sum=(d[x<<1].sum+d[x<<1|1].sum)%lth;
    }
    void built(int rt,int l,int r){
        if(l==r){
            d[rt].l=d[rt].r=l;d[rt].flag=d[rt].sum=0;
            return ;
        }
        int mid=(l+r)>>1;
        built(rt<<1,l,mid);
        built(rt<<1|1,mid+1,r);
        d[rt].l=d[rt<<1].l;d[rt].r=d[rt<<1|1].r;d[rt].flag=0;
        up(rt);
    }
    void update(int root,int l,int r){
        if(l<=d[root].l&&d[root].r<=r){
            d[root].flag+=1;d[root].sum=(d[root].sum+(d[root].r-d[root].l+1)%lth)%lth;
            return ;
        }
        push(root);
        int mid=(d[root].l+d[root].r)>>1;
        if(l<=mid) update(root<<1,l,r);
        if(r>mid) update(root<<1|1,l,r);
        up(root);
    }
    int ans;
    void querty(int root,int l,int r){
        if(l<=d[root].l&&d[root].r<=r){
            ans+=d[root].sum;
            return ;
        }
        int mid=(d[root].l+d[root].r)>>1;
        push(root);
        if(l<=mid) querty(root<<1,l,r);
        if(r>mid) querty(root<<1|1,l,r);
        up(root);
    }
    int Sum(int v,int t){
        int ans1=0;int vv=tp[v];
        while(vv!=1){
            if(t==1) update(1,p[vv],p[v]);
            else{
                ans=0;querty(1,p[vv],p[v]);
                ans1=(ans1+ans)%lth;
            }
            v=fa[vv];vv=tp[v];
        }
        if(t==1) update(1,1,p[v]);
        else{
            ans=0;querty(1,1,p[v]);
            ans1=(ans1+ans)%lth;
        }
        return ans1;
    }
    typedef struct List{
        int l,wei,z;
        friend bool operator <(List aa,List bb){
            return aa.l<bb.l;
        }
    }List;
    List dd[N<<1];
    int ans2[N];
    int main(){
        ios::sync_with_stdio(false);
        scanf("%d%d",&n,&q);cnt=0;
        int t;
        for(int i=1;i<=n;i++) son[i]=-1;
        for(int i=2;i<=n;i++){
            scanf("%d",&t);
            vec[t+1].push_back(i);
        }
        int x,y,z;int cnt1=0;
        memset(ans2,0,sizeof(ans2));
        for(int i=1;i<=q;i++){
            scanf("%d %d %d",&x,&y,&z);
            dd[++cnt1].l=x;dd[cnt1].wei=i;dd[cnt1].z=z+1;
            dd[++cnt1].l=y+1;dd[cnt1].wei=i;dd[cnt1].z=z+1;
        }
        sort(dd+1,dd+cnt1+1);
        dfs1(1,0,0);
    //  cout<<"sb"<<endl;
        dfs2(1,1);
        built(1,1,n);int u=1;
        for(int i=1;i<=cnt1;i++){
            if(dd[i].l==0) continue;
            while(u<=dd[i].l){
                Sum(u,1);u++;
            }
        //  Sum(u,1);
            int tt=Sum(dd[i].z,0);
            //cout<<dd[i].l<<" "<<dd[i].wei<<" "<<tt<<endl;
            ans2[dd[i].wei]=((tt-ans2[dd[i].wei])%lth+lth)%lth;
        }
        for(int i=1;i<=q;i++) printf("%d
    ",ans2[i]);
        return 0;
    }
  • 相关阅读:
    在宏块级冗余可调的多描述视频编码算法方面取得进展(转载)
    C++单例模式
    C++手动实现库函数
    C#操作java平台生成的公钥
    C++之位操作符
    Windows 8 应用栏
    Windows 8 本地数据存储
    Win8的页面缓存
    操作符sizeof
    three.js结合geoJson绘制中国地图
  • 原文地址:https://www.cnblogs.com/wang9897/p/8393351.html
Copyright © 2011-2022 走看看