P3241 [HNOI2015]开店

题解:动态点分治

建立点分树

每个点维护点分树子树内节点到这个节点和父亲节点距离的前缀和

二分查找锁定合法区间

对每个祖先分治中心查询路径和然后减去不合法子树内的路径和

注意:求大量LCA时用树剖

不开O2时少用STL

相乘炸int

lower_bound和upper_bound返回值边界

注意常数

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn=200009;
const int oo=1000000000;
typedef long long Lint;

int n,T,u;
int a[maxn];

int cntedge;
int head[maxn];
int to[maxn<<1],nex[maxn<<1],dist[maxn<<1];
void Addedge(int x,int y,int z){
    nex[++cntedge]=head[x];
    to[cntedge]=y;
    dist[cntedge]=z;
    head[x]=cntedge;
}

int nowsiz,root;
int vis[maxn];
int siz[maxn],g[maxn];
void Getsiz(int x,int fa){
    siz[x]=1;
    for(int i=head[x];i;i=nex[i]){
        if(vis[to[i]])continue;
        if(to[i]==fa)continue;
        Getsiz(to[i],x);
        siz[x]+=siz[to[i]];
    }
}
void Getroot(int x,int fa){
    siz[x]=1;
    g[x]=0;
    for(int i=head[x];i;i=nex[i]){
        if(vis[to[i]])continue;
        if(to[i]==fa)continue;
        Getroot(to[i],x);
        siz[x]+=siz[to[i]];
        g[x]=max(g[x],siz[to[i]]);
    }
    g[x]=max(g[x],nowsiz-siz[x]);
    if(g[x]<g[root])root=x;
}

int divfa[maxn];
void Sol(int x){
    vis[x]=1;
    Getsiz(x,0);
    for(int i=head[x];i;i=nex[i]){
        if(vis[to[i]])continue;
        root=0;nowsiz=siz[to[i]];
        Getroot(to[i],x);
        divfa[root]=x;
        Sol(root);
    }
}

int father[maxn],dep[maxn],d[maxn],top[maxn],hson[maxn];
void Dfs(int x,int fa){
    father[x]=fa;
    dep[x]=dep[fa]+1;
    siz[x]=1;
    for(int i=head[x];i;i=nex[i]){
        if(to[i]==fa)continue;
        d[to[i]]=d[x]+dist[i];
        Dfs(to[i],x);
        siz[x]+=siz[to[i]];
        if(siz[to[i]]>siz[hson[x]])hson[x]=to[i];
    }
}
void Dfs2(int x,int toppoint){
	top[x]=toppoint;
	if(!hson[x])return;
	Dfs2(hson[x],toppoint);
	for(int i=head[x];i;i=nex[i]){
		if(to[i]==father[x])continue;
		if(to[i]==hson[x])continue;
		Dfs2(to[i],to[i]);
	}
}

int Getlca(int u,int v){
	int tu=top[u];
	int tv=top[v];
	while(tu!=tv){
		if(dep[tu]<dep[tv]){
			swap(u,v);
			swap(tu,tv);
		}
		u=father[tu];
		tu=top[u];
	}
	if(dep[u]<dep[v])return u;
	else return v;
}

int Getdist(int x,int y){
    if((x==0)||(y==0))return 0;
    int lca=Getlca(x,y);
    return d[x]+d[y]-d[lca]-d[lca];
}

vector<int>G[maxn];
vector<Lint>S[maxn];
vector<Lint>S2[maxn];

int cmp(const int &rhs1,const int &rhs2){
    return a[rhs1]<a[rhs2];
}

int main(){
    scanf("%d%d%d",&n,&T,&u);
    for(int i=1;i<=n;++i)scanf("%d",&a[i]);
    for(int i=1;i<n;++i){
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        Addedge(x,y,z);
        Addedge(y,x,z);
    }
    
    Dfs(1,0);
    Dfs2(1,1);
    
    g[0]=oo;root=0;nowsiz=n;
    Getroot(1,0);
    Sol(root);
    
    for(int i=1;i<=n;++i){
        int x=i;
        while(x){
            G[x].push_back(i);
            x=divfa[x];
        }
    }
    
//	for(int i=1;i<=n;++i){
//		for(int j=1;j<=n;++j){
//			cout<<Getdist(i,j)<<' ';
//		}
//		cout<<endl;
//	}
    for(int i=1;i<=n;++i){
        sort(G[i].begin(),G[i].end(),cmp);
        Lint now=0,now2=0;
        for(int j=0;j<G[i].size();++j){
            now=now+Getdist(i,G[i][j]);
            now2=now2+Getdist(divfa[i],G[i][j]);
            S[i].push_back(now);
            S2[i].push_back(now2);
            G[i][j]=a[G[i][j]];
        }
//		printf("=->%d %d %d\n",i,now,now2);
    }
//	for(int i=1;i<=n;++i)cout<<d[i]<<' ';
//	cout<<endl;
    Lint ans=0;
    while(T--){
        int x,y,Lold,Rold;
        scanf("%d%d%d",&x,&Lold,&Rold);
        y=x;
        int t1=(Lold+ans)%u;
        int t2=(Rold+ans)%u;
        Lold=min(t1,t2);
        Rold=max(t1,t2);
//		cout<<Lold<<' '<<Rold<<endl;
        ans=0;
        int p=0;
//		cout<<ans<<endl;
//		for(int i=0;i<G[x].size();++i)cout<<G[x][i]<<' ';
//		cout<<endl;
        p=upper_bound(G[x].begin(),G[x].end(),Rold)-G[x].begin()-1;
        if(p>-1)ans+=S[x][p];
//		cout<<p<<endl;
        p=lower_bound(G[x].begin(),G[x].end(),Lold)-G[x].begin();
        if(p)ans-=S[x][p-1];
//		cout<<p<<endl;
//		cout<<ans<<endl;
        while(divfa[x]){
            Lint fdist=Getdist(divfa[x],y);
            int fa=divfa[x];
            
            p=upper_bound(G[fa].begin(),G[fa].end(),Rold)-G[fa].begin()-1;
            if(p>-1)ans+=S[fa][p]+fdist*(p+1);
//			cout<<p<<' ';
            p=lower_bound(G[fa].begin(),G[fa].end(),Lold)-G[fa].begin();
            if(p)ans-=S[fa][p-1]+fdist*p;
//			cout<<p<<endl;
//			cout<<ans<<endl;
            p=upper_bound(G[x].begin(),G[x].end(),Rold)-G[x].begin()-1;
            if(p>-1)ans-=S2[x][p]+fdist*(p+1);
            p=lower_bound(G[x].begin(),G[x].end(),Lold)-G[x].begin();
            if(p)ans+=S2[x][p-1]+fdist*p;
//			cout<<ans<<endl;
            x=divfa[x];
        }
        printf("%lld\n",ans);
    }
    return 0;
}

  

posted @ 2018-02-27 19:56  ws_zzy  阅读(180)  评论(0编辑  收藏  举报