zoukankan      html  css  js  c++  java
  • BZOJ 4012 树链剖分+主席树

    思路:
    http://blog.csdn.net/lych_cys/article/details/50763073
    lych的题解…… 写得很详细

    //By SiriusRen
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define int long long
    #define N 300050
    int n,Q,A,age[N],w[N],v[N],next[N],first[N],tot,rev[N],root[N];
    int xx,yy,zz,size[N],fa[N],top[N],cnt,p[N],dis[N],son[N],deep[N];
    int ans,edg[N],sum[N];
    struct Node{int age,id;}node[N],jy;
    struct Tree{int l,r,sum,lazy;}tr[N*40];
    bool operator<(Node a,Node b){return a.age<b.age;}
    void add(int x,int y,int z){w[tot]=z,v[tot]=y,next[tot]=first[x],first[x]=tot++;}
    void dfs(int x){
        size[x]=1;
        for(int i=first[x];~i;i=next[i])if(v[i]!=fa[x]){
            fa[v[i]]=x,dis[v[i]]=dis[x]+w[i],edg[v[i]]=w[i];
            deep[v[i]]=deep[x]+1,dfs(v[i]);
            size[x]+=size[v[i]];
            if(size[son[x]]<size[v[i]])son[x]=v[i];
        }
    }
    void dfs(int x,int tp){
        top[x]=tp,p[x]=++cnt,rev[cnt]=x;
        if(son[x])dfs(son[x],tp);
        for(int i=first[x];~i;i=next[i])
            if(v[i]!=fa[x]&&v[i]!=son[x])dfs(v[i],v[i]);
    }
    void insert(int l,int r,int x,int &y,int L,int R){
        y=++cnt;int mid=(l+r)>>1;
        tr[y].sum=tr[x].sum,tr[y].lazy=tr[x].lazy;
        if(l==L&&r==R){tr[y].l=tr[x].l,tr[y].r=tr[x].r,tr[y].lazy++;return;}
        tr[y].sum+=sum[R]-sum[L-1];
        if(mid<L)tr[y].l=tr[x].l,insert(mid+1,r,tr[x].r,tr[y].r,L,R);
        else if(mid>=R)tr[y].r=tr[x].r,insert(l,mid,tr[x].l,tr[y].l,L,R);
        else insert(l,mid,tr[x].l,tr[y].l,L,mid),insert(mid+1,r,tr[x].r,tr[y].r,mid+1,R);
    }
    void insert(int x,int i){
        root[i]=root[i-1];
        while(top[x]!=1)insert(1,n,root[i],root[i],p[top[x]],p[x]),x=fa[top[x]];
        insert(1,n,root[i],root[i],1,p[x]);
    }
    int query(int l,int r,int x,int y,int L,int R){
        int mid=(l+r)>>1,temp=(tr[y].lazy-tr[x].lazy)*(sum[R]-sum[L-1]);
        if(l>=L&&r<=R){return temp+tr[y].sum-tr[x].sum;}
        if(mid<L)return temp+query(mid+1,r,tr[x].r,tr[y].r,L,R);
        else if(mid>=R)return temp+query(l,mid,tr[x].l,tr[y].l,L,R);
        else return temp+query(l,mid,tr[x].l,tr[y].l,L,mid)+query(mid+1,r,tr[x].r,tr[y].r,mid+1,R);
    }
    int query(int x,int y,int u){
        int temp=0;
        while(top[u]!=1)temp+=query(1,n,root[x],root[y],p[top[u]],p[u]),u=fa[top[u]];
        return temp+query(1,n,root[x],root[y],1,p[u]);
    }
    signed main(){
        memset(first,-1,sizeof(first));
        scanf("%lld%lld%lld",&n,&Q,&A);
        for(int i=1;i<=n;i++)scanf("%lld",&node[i].age),node[i].id=i;
        sort(node+1,node+1+n);
        for(int i=1;i<n;i++)
            scanf("%lld%lld%lld",&xx,&yy,&zz),add(xx,yy,zz),add(yy,xx,zz);
        dfs(1),dfs(1,1),cnt=0;
        for(int i=1;i<=n;i++)sum[i]=sum[i-1]+edg[rev[i]];
        for(int i=1;i<=n;i++)insert(node[i].id,i);
        for(int i=1;i<=Q;i++){
            int u,a,b,l,r;
            scanf("%lld%lld%lld",&u,&a,&b);
            a=(a+ans)%A,b=(b+ans)%A;
            if(a>b)swap(a,b);
            jy.age=a,l=lower_bound(node+1,node+1+n,jy)-node-1;
            jy.age=b,r=upper_bound(node+1,node+1+n,jy)-node-1;
            ans=tr[root[r]].sum-tr[root[l]].sum+dis[u]*(r-l)-2*query(l,r,u);
            printf("%lld
    ",ans);
        }
    }

    这里写图片描述

  • 相关阅读:
    实验二 用机器指令和汇编指令编程
    实验1查看CPU和内存,用机器指令和汇编语言指令编程
    汇编第9~15章——汇编基础知识梳理与总结
    汇编第5~8章——基础知识梳理与总结
    实验9 根据材料编程
    实验5 编写、调试具有多个段的程序
    实验4 [BX]和loop指令
    实验3 编程、编译、连接、跟踪
    实验2 用机器指令和汇编指令编程
    实验1 查看CPU和内存,用机器指令和汇编指令编程
  • 原文地址:https://www.cnblogs.com/SiriusRen/p/6532057.html
Copyright © 2011-2022 走看看