zoukankan      html  css  js  c++  java
  • bzoj3626

    题解:

    树链剖分+离线处理

    先考虑一个暴力的方法

    把z从底往上面的父亲每一个加一

    然后对于l-r中的节点

    计算从当前节点到根节点的总和

    那么就是答案

    于是我们可以离线预处理

    代码:

    #include<bits/stdc++.h>
    typedef long long ll;
    const int M=201314,N=400005;
    using namespace std;
    int n,m,cnt,place,x,son[N],last[N],fa[N],belong[N],pl[N],deep[N];
    struct edge{int to,next;}e[N];
    struct que{int z,ans1,ans2;}q[N];
    struct data{int num,p;bool flag;}a[100005];
    struct seg{int l,r,sum,tag,size;}t[N];
    bool operator<(data a,data b)
    {
        return a.p<b.p;
    }
    void insert(int u,int v)
    {
        e[++cnt].to=v;
        e[cnt].next=last[u];
        last[u]=cnt;
    }
    void dfs1(int x)
    {
        son[x]=1;
        for (int i=last[x];i;i=e[i].next)
         {
            if(e[i].to==fa[x])continue;
            deep[e[i].to]=deep[x]+1;
            fa[e[i].to]=x;
            dfs1(e[i].to);
            son[x]+=son[e[i].to];
         }
    }
    void dfs2(int x,int chain)
    {
        belong[x]=chain;
        pl[x]=++place;
        int k=n;
        for(int i=last[x];i;i=e[i].next)
         if(e[i].to!=fa[x]&&son[e[i].to]>son[k])k=e[i].to;
        if(k!=n)dfs2(k,chain);
        for(int i=last[x];i;i=e[i].next)
         if(e[i].to!=fa[x]&&e[i].to!=k)dfs2(e[i].to,e[i].to);
    }
    void pushdown(int k)
    {
        if (t[k].l==t[k].r||!t[k].tag)return;
        int tag=t[k].tag;t[k].tag=0;
        t[k<<1].sum=t[k<<1].sum+t[k<<1].size*tag;
        t[k<<1|1].sum=t[k<<1|1].sum+t[k<<1|1].size*tag;
        t[k<<1].tag=t[k<<1].tag+tag;
        t[k<<1|1].tag=t[k<<1|1].tag+tag;
    }
    void build(int k,int l,int r)
    {
        t[k].l=l;t[k].r=r;t[k].size=r-l+1;
        if (l==r)return;
        int mid=(l+r)>>1;
        build(k<<1,l,mid);
        build(k<<1|1,mid+1,r);
    }
    void update(int k,int x,int y)
    {
        pushdown(k);
        int l=t[k].l,r=t[k].r;
        if (l==x&&y==r)
         {
            t[k].tag++;t[k].sum+=t[k].size;
            return;
         }
        int mid=(l+r)>>1;
        if (y<=mid)update(k<<1,x,y);
        else if (x>mid)update(k<<1|1,x,y);
        else 
         {
            update(k<<1,x,mid);
            update(k<<1|1,mid+1,y);
         }
        t[k].sum=t[k<<1].sum+t[k<<1|1].sum;
    }
    void solve_update(int x,int f)
    {
        while (belong[x]!=belong[f])
         {
            update(1,pl[belong[x]],pl[x]);
            x=fa[belong[x]];
         }
        update(1,pl[f],pl[x]);
    }
    int query(int k,int x,int y)
    {
        pushdown(k);
        int l=t[k].l,r=t[k].r;
        if (l==x&&y==r)return t[k].sum;
        int mid=(l+r)>>1;
        if (y<=mid)return query(k<<1,x,y);
        else if (x>mid)return query(k<<1|1,x,y);
        else return query(k<<1,x,mid)+query(k<<1|1,mid+1,y);
    }
    int solve_query(int x,int f)
    {
        int sum=0;
        while (belong[x]!=belong[f])
         {
            sum+=query(1,pl[belong[x]],pl[x]);
            sum%=M;
            x=fa[belong[x]];
         }
        sum+=query(1,pl[f],pl[x]);sum%=M;
        return sum;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for (int i=1;i<n;i++)scanf("%d",&x),insert(x,i);
        int tot=0;
        for (int i=1;i<=m;i++)
         {
            int l,r;
            scanf("%d%d%d",&l,&r,&q[i].z);
            a[++tot].p=l-1;a[tot].num=i;a[tot].flag=0;
            a[++tot].p=r;a[tot].num=i;a[tot].flag=1;
         }
        build(1,1,n);
        sort(a+1,a+tot+1);
        dfs1(0);dfs2(0,0);
        int now=-1;
        for (int i=1;i<=tot;i++)
         {
            while (now<a[i].p)
             {
                now++;
                solve_update(now,0);
             }
            int t=a[i].num;
            if (!a[i].flag)q[t].ans1=solve_query(q[t].z,0);
            else q[t].ans2=solve_query(q[t].z,0);
         }
        for (int i=1;i<=m;i++)printf("%d
    ",(q[i].ans2-q[i].ans1+M)%M);
        return 0;
    }
  • 相关阅读:
    送给有缘的人,2007年9月20日可买入股票
    上次9.19推荐的兰太实业停牌的公告,有持有的朋友可查看
    送给有缘的人,2007年9月24日可买入股票
    对古越龙山的惆怅
    将PDA矢量图控件开源
    读取PE文件的导入表
    [非原创] 用于将真彩色图像降级为索引图像的八叉树算法
    读取PE文件的资源表
    [VC6] 图像文件格式数据查看器
    关于 AlphaBlend 和 32bpp 的反锯齿图标
  • 原文地址:https://www.cnblogs.com/xuanyiming/p/7994141.html
Copyright © 2011-2022 走看看