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


    独立写出来+想出来的,1.5h就切了~

    建立点分树,然后用 $vector$ 暴力存所有子节点,然后二分一下子就可以了. 

    #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
    ",lastans=work(L,R,u));   
    	}   
    	return 0; 
    }
    

      

  • 相关阅读:
    vue-常用指令汇总
    vue-插槽和具名插槽
    vue-传值校验
    vue-动态组件
    vue-组件
    zend studio 快捷键收集
    php调试工具firephp
    zend studio插件
    MySQL各个版本区别
    PHP 中 Date 函数与实际时间相差8小时的解决方法
  • 原文地址:https://www.cnblogs.com/guangheli/p/11448981.html
Copyright © 2020-2023  润新知