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\n",ans);
    }
}

这里写图片描述

posted @ 2017-01-29 21:21  SiriusRen  阅读(138)  评论(0编辑  收藏  举报