luogu 3241 [HNOI2015]开店 动态点分治+二分+vector

Code: 

#include <cstdio>  
#include <vector> 
#include <algorithm>    
#define N 300000 
#define ll long long    
#define setIO(s) freopen(s".in","r",stdin) , freopen(s".out","w",stdout) 
using namespace std;         
int edges,n; 
int hd[N],to[N<<1],nex[N<<1],val[N<<1]; 
void add(int u,int v,int c) 
{
	nex[++edges]=hd[u],hd[u]=edges,to[edges]=v,val[edges]=c; 
}  
namespace tree
{   
	int size[N],son[N],top[N],fa[N],dep[N],dis[N];
	void dfs1(int u,int ff)
	{
		fa[u]=ff,size[u]=1;
		for(int i=hd[u];i;i=nex[i])
			if(to[i]!=ff)
			{
				dep[to[i]]=dep[u]+1,dis[to[i]]=dis[u]+val[i];    
				dfs1(to[i],u);
				size[u]+=size[to[i]];
				if(size[to[i]]>size[son[u]]) son[u]=to[i];
			}
	} 
	void dfs2(int u,int tp)
	{
		top[u]=tp;
		if(son[u]) dfs2(son[u],tp); 
		for(int i=hd[u];i;i=nex[i]) 
			if(to[i]!=son[u]&&to[i]!=fa[u]) 
				dfs2(to[i],to[i]); 
	}
	int LCA(int x,int y)
	{
		while(top[x]!=top[y]) 
			dep[top[x]]>dep[top[y]]?x=fa[top[x]]:y=fa[top[y]];
		return dep[x]<dep[y]?x:y; 
	} 
	int Dis(int x,int y)
	{
		return dis[x]+dis[y]-(dis[LCA(x,y)]<<1);   
	}
};   
int root,sn; 
int age[N],size[N],mx[N],vis[N],Fa[N];     
struct Node 
{
	int v,d; 
	ll tot; 
	Node(int v=0,int d=0,ll tot=0):v(v),d(d),tot(tot){} 
};  
vector<Node>G[N],F[N];       
bool cmp(Node a,Node b)
{
	return a.v<b.v;       
}
void getroot(int u,int ff)
{ 
	size[u]=1,mx[u]=0; 
	for(int i=hd[u];i;i=nex[i]) 
		if(to[i]!=ff&&!vis[to[i]]) 
			getroot(to[i],u),size[u]+=size[to[i]],mx[u]=max(mx[u],size[to[i]]); 
	mx[u]=max(mx[u],sn-size[u]);  
	if(mx[u]<mx[root]) root=u;    
}  
void dfs(int u,int ff,int rt,int dep)
{  
	G[rt].push_back(Node(age[u],dep,0));   
	if(Fa[rt]) F[rt].push_back(Node(age[u],tree::Dis(Fa[rt],u), 0));      
	for(int i=hd[u];i;i=nex[i]) 
	{
		int v=to[i]; 
		if(v==ff||vis[v]) continue;        
		dfs(v,u,rt,dep+val[i]);     
	}  
}
void solve(int u) 
{  
	vis[u]=1;  
	G[u].push_back(Node(-100,0,0)); 
	F[u].push_back(Node(-100,0,0)); 
	G[u].push_back(Node(1000000004,0,0));    
	F[u].push_back(Node(1000000004,0,0));            
	dfs(u,0,u,0);                      
	sort(G[u].begin(),G[u].end(),cmp); 
	sort(F[u].begin(),F[u].end(),cmp);  
	for(int i=1;i<F[u].size();++i) F[u][i].tot=F[u][i-1].tot+1ll*F[u][i].d;      
	for(int i=1;i<G[u].size();++i) G[u][i].tot=G[u][i-1].tot+1ll*G[u][i].d;      
	for(int i=hd[u];i;i=nex[i]) 
		if(!vis[to[i]]) 
		{
			sn=size[to[i]],root=0,getroot(to[i],u),Fa[root]=u, solve(root);      
		}
} 
ll work(int L,int R,int u) 
{   
	ll re=0; 
	int l,r,mid,ans1=0,ans2=0;  
	l=0,r=G[u].size()-1; 
	while(l<=r) 
	{
		mid=(l+r)>>1;     
		if(G[u][mid].v>=L) ans1=mid,r=mid-1; 
		else l=mid+1;  
	}    
	l=0,r=G[u].size()-1; 
	while(l<=r) 
	{
		mid=(l+r)>>1; 
		if(G[u][mid].v<=R) ans2=mid,l=mid+1; 
		else r=mid-1;    
	}   
	if(ans1>0&&ans2<G[u].size()-1&&ans1<=ans2) 
		re+=G[u][ans2].tot-G[u][ans1-1].tot;    
	int U=u;          
	for(;Fa[u];u=Fa[u]) 
	{ 
		int anss1=ans1,anss2=ans2;        
		l=0,r=G[Fa[u]].size()-1,ans1=0;   
		while(l<=r) 
		{
			mid=(l+r)>>1;     
			if(G[Fa[u]][mid].v>=L) ans1=mid,r=mid-1; 
			else l=mid+1;  
		}    
		l=0,r=G[Fa[u]].size()-1,ans2=0;      
		while(l<=r) 
		{
			mid=(l+r)>>1; 
			if(G[Fa[u]][mid].v<=R) ans2=mid,l=mid+1;
			else r=mid-1;    
		}     
		if(ans1>ans2) continue;  
		ll tmp=0; 
		tmp+=G[Fa[u]][ans2].tot-G[Fa[u]][ans1-1].tot;  
		if(anss2>=anss1) tmp-=F[u][anss2].tot-F[u][anss1-1].tot;                          
		if(anss1<=anss2) 
			tmp=tmp+(ll)(ans2-ans1-(anss2-anss1+1)+1)*1ll*tree::Dis(U,Fa[u]);                      
		else  
			tmp=tmp+(ll)(ans2-ans1+1)*1ll*tree::Dis(U,Fa[u]);    
		re+=tmp;     
	}
	return re;                        
}
int main() 
{
	// setIO("input");   
	int Q,A,i,j; 
	scanf("%d%d%d",&n,&Q,&A); 
	for(i=1;i<=n;++i) scanf("%d",&age[i]);           
	for(i=1;i<n;++i) 
	{
		int a,b,c; 
		scanf("%d%d%d",&a,&b,&c); 
		add(a,b,c),add(b,a,c); 
	}   
	tree::dfs1(1,0);
	tree::dfs2(1,1); 
	mx[0]=sn=n,getroot(1,0),solve(root);         
	ll lastans=0; 
	for(int cas=1;cas<=Q;++cas) 
	{
		int u,a,b,L,R; 
		scanf("%d%d%d",&u,&a,&b);            
		L=(a+lastans)%A,R=(b+lastans)%A; 
		if(L>R) swap(L,R);        
		printf("%lld\n",lastans=work(L,R,u));   
	}   
	return 0; 
}

  

猜你喜欢

转载自www.cnblogs.com/guangheli/p/11448981.html