zoukankan      html  css  js  c++  java
  • luogu P3345 [ZJOI2015]幻想乡战略游戏

    算是一道动态点分治入门题(我太弱了加起来学了三天)。

    拿到题首先考虑如何暴力,我们可以随机钦定一个点(不妨就设(1))为根节点,然后算出补给站设在该点的总花费,然后算出补给站在每个儿子时的总花费,显然最多只会有一个儿子花费比它(当前点)本身小(当且仅当(sum[u]<sum[son] imes 2)(sum[i])表示(i)号点子树内拥有的军队总数),如果存在这个花费比它小的儿子,就跳到它儿子上重复上述过程,如果不存在这个儿子,那么这个点就是答案。

    显然这样写一条链就没了,所以考虑用点分树来优化这个过程(下面其实就是动态点分治的套路了,跟本题关系不太大)。

    记三个值(sum[i],dis1[i],dis2[i])分别表示当前子树内的军队总数、当前子树内的点到当前子树根节点的总花费、当前子树内的点到当前子树根节点的父亲节点的总花费(注意这里所有子树的概念都是在点分树中)。

    这三个值在修改是可以暴力跳点分树维护,查询的时候也是暴力跳点分树就好了。时间复杂度(O(nlog^2n))

    (tips:)今天学会了如何(O(nlogn))预处理(ST)表然后(O(1))(LCA),其实就是类似一个欧拉序的东西,按照(dep)建立(ST)表,然后就能(O(1))得到(LCA)了。

    代码:

    #pragma GCC optimize(2)
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #define rint int
    
    using namespace std;
    
    typedef long long LL;
    const int N=1000009;
    int n,Q,root,head[N],cnt,F[N],log[N];
    LL dis1[N],dis2[N],sum[N];
    struct Edge
    {
    	int nxt,to,w;
    }g[N*2];
    struct G
    {
    	int head[N],cnt,f[N][30],dep[N],del[N],siz[N],Euler[N],Fst[N],Index;
    	LL dis[N];
    	struct Edge
    	{
    		int nxt,to,w;
    	}g[N*2];
    	
    	void add(int from,int to,int w)
    	{
    		g[++cnt].nxt=head[from];
    		g[cnt].to=to;
    		g[cnt].w=w;
    		head[from]=cnt;
    	}
    	int LCA(int x,int y)
    	{
    		if(Fst[x]>Fst[y])
    			swap(x,y);
    		x=Fst[x],y=Fst[y];
    		int k=log[y-x+1];
    		return dep[f[x][k]]<dep[f[y-(1<<k)+1][k]]?f[x][k]:f[y-(1<<k)+1][k];
    	}
    	void dfs(int x,int fa)
    	{
    		Euler[++Index]=x,Fst[x]=Index,f[Index][0]=x;
    		for (rint i=head[x];i;i=g[i].nxt)
    		{
    			int v=g[i].to;
    			if(v==fa)
    				continue;
    			dep[v]=dep[x]+1,dis[v]=dis[x]+g[i].w;
    			dfs(v,x);
    			Euler[++Index]=x,f[Index][0]=x;
    		}
    	}
    	int Get_dis(int x,int y)
    	{
    		return dis[x]+dis[y]-2*dis[LCA(x,y)];
    	}
    	void DFS(int x,int fa)
    	{
    		siz[x]=1;
    		for (rint i=head[x];i;i=g[i].nxt)
    		{
    			int v=g[i].to;
    			if(v==fa||del[v])
    				continue;
    			DFS(v,x);
    			siz[x]+=siz[v];
    		}
    	}
    	int Get_Weight(int x)
    	{
    		DFS(x,-1);
    		int k=siz[x]/2,fa=-1;
    		while(1)
    		{
    			int tmp=0;
    			for (rint i=head[x];i;i=g[i].nxt)
    			{
    				int v=g[i].to;
    				if(v==fa||del[v])
    					continue;
    				if(siz[v]>siz[tmp])
    					tmp=v;
    			}
    			if(siz[tmp]<=k)
    				return x;
    			fa=x,x=tmp;
    		}
    	}
    	void work()
    	{
    		dfs(1,-1);
    		for (int j=1;1<<j<=Index;j++)
    			for (int i=1;i+(1<<j)-1<=Index;i++)
    				if(dep[f[i][j-1]]<dep[f[i+(1<<j-1)][j-1]])
    					f[i][j]=f[i][j-1];
    				else
    					f[i][j]=f[i+(1<<j-1)][j-1];
    	}
    }T;
    
    void add(int from,int to,int w)
    {
    	g[++cnt].nxt=head[from];
    	g[cnt].to=to;
    	g[cnt].w=w;
    	head[from]=cnt;
    }
    
    int read()
    {
    	char c=getchar();
    	int x=0,f=1;
    	while(c<'0'||c>'9')
    	{
    		if(c=='-')
    			f=-1;
    		c=getchar();
    	}
    	while(c>='0'&&c<='9')
    		x=x*10+c-'0',c=getchar();
    	return x*f;
    }
    
    void init()
    {
    	log[0]=-1;
    	for (int i=1;i<=N-9;i++)
    		log[i]=log[i>>1]+1;
    	n=read(),Q=read();
    	for (rint i=1;i<n;i++)
    	{
    		int x,y,z;
    		x=read(),y=read(),z=read();
    		T.add(x,y,z),T.add(y,x,z);
    	}
    	T.work();
    }
    
    void build(int fa)
    {
    	T.del[fa]=1;
    	for (rint i=T.head[fa];i;i=T.g[i].nxt)
    	{
    		int v=T.g[i].to;
    		if(T.del[v]||v==fa)
    			continue;
    		int w=T.Get_Weight(v);
    		F[w]=fa,add(fa,w,v),add(w,fa,v);
    		build(w);
    	}
    }
    
    void Modify(int x,int y)
    {
    	//printf("eijfie %d %d
    ",x,y);
    	for (rint i=x;i;i=F[i])
    	{
    		sum[i]+=y;
    		if(i!=root)
    		{
    			LL fuck=1LL*T.Get_dis(x,F[i])*y;
    			//if(x==3&&y==1)
    				//printf("???%d %d %d
    ",x,F[i],T.Get_dis(2,3));
    			dis1[F[i]]+=fuck,dis2[i]+=fuck;
    		}
    	}
    }
    
    LL calc(int x)
    {
    	LL ans=dis1[x];
    	for (rint i=x;F[i];i=F[i])
    	{
    		ans+=dis1[F[i]]-dis2[i];
    		ans+=(sum[F[i]]-sum[i])*T.Get_dis(x,F[i]);
    	}
    	return ans;
    }
    
    LL Query(int x)
    {
    	LL last=calc(x);
    	//printf("fuck%d %d
    ",x,last);
    	for (rint i=head[x];i;i=g[i].nxt)
    	{
    		if(g[i].to==F[x])
    			continue;
    		LL now=calc(g[i].w);
    		//printf("%lld %d
    ",now,g[i].w);
    		if(now<last)
    			return Query(g[i].to);
    	}
    	return last;
    }
    
    void print(int x,int fa)
    {
    	printf("%d %d
    ",fa,x);
    	for (rint i=head[x];i;i=g[i].nxt)
    	{
    		int v=g[i].to;
    		if(v==fa)
    			continue;
    		print(v,x);
    	}
    }
    
    void work()
    {
    	root=T.Get_Weight(1);
    	build(root);
    	//printf("weoigwi%d
    ",T.LCA(2,3));
    	//print(root,-1);
    	for (rint _=1;_<=Q;_++)
    	{
    		int x,y;
    		x=read(),y=read();
    		Modify(x,y);
    		//if(_==4)
    			//printf("wyj%d
    ",dis1[2]);
    		printf("%lld
    ",Query(root));
    	}
    }
    
    int main()
    {
    	init();
    	work();
    	return 0;
    }
    
    由于博主比较菜,所以有很多东西待学习,大部分文章会持续更新,另外如果有出错或者不周之处,欢迎大家在评论中指出!
  • 相关阅读:
    null in ABAP and nullpointer in Java
    SAP ABAP SM50事务码和Hybris Commerce的线程管理器
    Hybris service layer和SAP CRM WebClient UI架构的横向比较
    SAP ABAP和Linux系统里如何检查网络传输的数据量
    SAP CRM WebClient UI和Hybris的controller是如何被调用的
    SAP CRM和Cloud for Customer订单中的业务伙伴的自动决定机制
    SAP CRM WebClient UI和Hybris CommerceUI tag的渲染逻辑
    SAP BSP和JSP页面里UI元素的ID生成逻辑
    微信jsapi支付
    微信jsapi退款操作
  • 原文地址:https://www.cnblogs.com/With-penguin/p/12724745.html
Copyright © 2011-2022 走看看