首页 > 其他分享 >P10603 BZOJ4372 烁烁的游戏 题解

P10603 BZOJ4372 烁烁的游戏 题解

时间:2024-09-27 15:23:18浏览次数:9  
标签:烁烁 P10603 int 题解 top 200010 dep siz son

题目传送门

前置知识

动态树分治 | 动态开点线段树 | 标记永久化

解法

考虑动态点分治。

两种操作本质上是将 luogu P6329 【模板】点分树 | 震波 的操作互换了下,将原需支持单点修改、区间查询的数据结构换成需支持区间修改、单点查询的数据结构即可。

区间修改、单点查询的动态开点线段树可以考虑标记永久化。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define ull unsigned long long
#define sort stable_sort 
#define endl '\n'
struct node
{
	int nxt,to;
}e[200010];
int head[200010],ask,cnt=0;
void add(int u,int v)
{
	cnt++;
	e[cnt].nxt=head[u];
	e[cnt].to=v;
	head[u]=cnt;
}
struct LCA
{
	int siz[200010],fa[200010],dep[200010],son[200010],top[200010];
	void init()
	{
		dfs1(1,0);
		dfs2(1,1);
	}
	void dfs1(int x,int father)
	{
		siz[x]=1;
		fa[x]=father;
		dep[x]=dep[father]+1;
		for(int i=head[x];i!=0;i=e[i].nxt)
		{
			if(e[i].to!=father)
			{
				dfs1(e[i].to,x);
				siz[x]+=siz[e[i].to];
				son[x]=(siz[e[i].to]>siz[son[x]])?e[i].to:son[x];
			}
		}
	}
	void dfs2(int x,int id)
	{
		top[x]=id;
		if(son[x]!=0)
		{
			dfs2(son[x],id);
			for(int i=head[x];i!=0;i=e[i].nxt)
			{
				if(e[i].to!=son[x]&&e[i].to!=fa[x])
				{
					dfs2(e[i].to,e[i].to);
				}
			}
		}
	}
	int lca(int u,int v)
	{
		while(top[u]!=top[v])
		{
			if(dep[top[u]]>dep[top[v]])
			{
				u=fa[top[u]];
			}
			else
			{
				v=fa[top[v]];
			}
		}
		return (dep[u]<dep[v])?u:v;
	}
	int get_dis(int x,int y)
	{
		return dep[x]+dep[y]-2*dep[lca(x,y)];
	}
}L;
struct SMT
{
	int root[200010],rt_sum=0;
	struct SegmentTree
	{
		int ls,rs,lazy;
	}tree[200010<<5];
	#define lson(rt) (tree[rt].ls)
	#define rson(rt) (tree[rt].rs)
	int build_rt()
	{
		rt_sum++;
		lson(rt_sum)=rson(rt_sum)=tree[rt_sum].lazy=0;
		return rt_sum;
	}
	void update(int &rt,int l,int r,int x,int y,int val)
	{	
		if(rt==0)
		{
			rt=build_rt();
		}
		if(x<=l&&r<=y)
		{		
			tree[rt].lazy+=val;
			return;
		}
		int mid=(l+r)/2;
		if(x<=mid)
		{
			update(lson(rt),l,mid,x,y,val);
		}
		if(y>mid)
		{
			update(rson(rt),mid+1,r,x,y,val);
		}
	}
	int query(int rt,int l,int r,int pos)
	{
		if(rt==0)
		{
			return 0;
		}
		if(l==r)
		{
			return tree[rt].lazy;
		}
		int mid=(l+r)/2;
		if(pos<=mid)
		{
			return query(lson(rt),l,mid,pos)+tree[rt].lazy;
		}
		else
		{
			return query(rson(rt),mid+1,r,pos)+tree[rt].lazy;
		}
	}
}T[2];
struct Divide_On_Tree
{
	int siz[200010],weight[200010],vis[200010],fa[200010],center=0;
	void init(int n)
	{
		center=0;
		get_center(1,0,n);
		get_siz(center,0);
		build(center);
	}
	void get_center(int x,int fa,int n)
	{
		siz[x]=1;
		weight[x]=0;
		for(int i=head[x];i!=0;i=e[i].nxt)
		{
			if(e[i].to!=fa&&vis[e[i].to]==0)
			{
				get_center(e[i].to,x,n);
				siz[x]+=siz[e[i].to];
				weight[x]=max(weight[x],siz[e[i].to]);
			}
		}
		weight[x]=max(weight[x],n-siz[x]);
		if(weight[x]<=n/2)
		{
			center=x;
		}
	}
	void get_siz(int x,int fa)
	{
		siz[x]=1;
		for(int i=head[x];i!=0;i=e[i].nxt)
		{
			if(e[i].to!=fa&&vis[e[i].to]==0)
			{
				get_siz(e[i].to,x);
				siz[x]+=siz[e[i].to];
			}
		}
	}
	void build(int x)
	{
		vis[x]=1;
		for(int i=head[x];i!=0;i=e[i].nxt)
		{
			if(vis[e[i].to]==0)
			{
				center=0;
				get_center(e[i].to,0,siz[e[i].to]);
				get_siz(center,0);
				fa[center]=x;
				build(center);
			}
		}
	}
	void update(int x,int k,int val)
	{
		T[0].update(T[0].root[x],0,ask,0,k,val);
		for(int rt=x;fa[rt]!=0;rt=fa[rt])
		{
			if(L.get_dis(fa[rt],x)<=k)
			{
				T[0].update(T[0].root[fa[rt]],0,ask,0,k-L.get_dis(fa[rt],x),val);
				T[1].update(T[1].root[rt],0,ask,0,k-L.get_dis(fa[rt],x),val);
			}
		}
	}
	int query(int x)
	{
		int ans=T[0].query(T[0].root[x],0,ask,0);
		for(int rt=x;fa[rt]!=0;rt=fa[rt])
		{
			ans+=T[0].query(T[0].root[fa[rt]],0,ask,L.get_dis(fa[rt],x));
			ans-=T[1].query(T[1].root[rt],0,ask,L.get_dis(fa[rt],x));
		}
		return ans;
	}
}D;
int main()
{
	int n,m,u,v,x,d,w,i;
	char pd;
	cin>>n>>m;
	ask=n;
	for(i=1;i<=n-1;i++)
	{
		cin>>u>>v;
		add(u,v);
		add(v,u);
	}
	L.init();
	D.init(n);
	for(i=1;i<=m;i++)
	{
		cin>>pd;
		if(pd=='Q')
		{
			cin>>x;
			cout<<D.query(x)<<endl;
		}
		else
		{
			cin>>x>>d>>w; 
			D.update(x,d,w);
		}
	}
	return 0;
}

标签:烁烁,P10603,int,题解,top,200010,dep,siz,son
From: https://www.cnblogs.com/The-Shadow-Dragon/p/18435824

相关文章

  • Light Bulbs (Hard Version) 题解
    提供一个非常另类的解法,没有异或哈希,没有建图,没有缩点和强连通分量,而是使用了并查集和线段树的算法。由于每个颜色恰好有两种,我们考虑把两个颜色的位置\(i,j\)变成一段区间\([i,j]\)(\(i<j\)),然后每个颜色就能用一段区间\([l,r]\)表示。根据题意,如果我们激活了一个区间\([l,......
  • 【MX-J3-T3+】Tuple+ 题解
    一个比较自然的思路就是对于每个三元组\((u_i,v_i,w_i)\),把\((v_i,w_i)\)这个二元组放在属于\(u_i\)的vector里面。然后对于每一个\(i\in[1,n-3]\),把\(i\)的vector里面的所有二元组\((x,y)\)当作一条连接\(x,y\)的无向边,则我们的目的是在图中找出所有的三元环\(......
  • [ARC115E] LEQ and NEQ 题解
    我这场打的VP,结果E思考的时间比A还少。。但是我觉得我能想出这道题还是很有意义的,写篇题解记录一下。首先应该都不难想到动态规划吧?我们先使用暴力DP:设\(dp_{i,j}\)表示处理完前\(i\)个数,第\(i\)个数为\(j\)的方案数。我们考虑进行分类讨论:\(a_i≥a_{i-1}\):此时......
  • 9.27今日错题解析(软考)
    目录前言信息安全——网络攻击算法基础——二分查找数据库系统——数据库设计过程前言这是用来记录我每天备考软考设计师的错题的,今天知识点为网络攻击、二分查找和数据库设计过程,大部分错题摘自希赛中的题目,但相关解析是原创,有自己的思考,为了复习:),最后希望各位报考......
  • [GXOI/GZOI2019] 逼死强迫症 题解
    看到\(N\leq2\times10^9\)的范围,一眼矩阵快速幂优化DP。首先考虑朴素DP怎么写。根据题目所给信息,我们设\(dp_{i,0}\)表示前面\(i\)个方砖,并且已经使用了\(2\)个\(1\times1\)的方砖,\(dp_{i,1}\)则表示前面\(i\)个方砖,没有使用任何一个\(1\times1\)的方砖。......
  • [CERC2015] Digit Division 题解
    \(O(n^2)\)做法和大部分人最开始一样,我也想的是DP。设\(dp_i\)表示用前面\(i\)个字符拆分得到的答案。既然是统计方案数,我们肯定是根据前面的答案累加。考虑在\([1,i-1]\)中选择一个\(j\),如果\([j+1,i]\)的字符组成的数字能够被\(m\)整除,那么\(dp_i\)就可以累加......
  • [JLOI2015] 有意义的字符串 题解
    拿到题目,我们首先分析一下这个奇怪的式子:\[\lfloor(\frac{b+\sqrt{d}}{2})^n\rfloor~\text{mod}~p\]重点肯定是在里面的那个式子里面,最显眼的肯定也就是那个\(\sqrt{d}\),根据整体形式,我们可以联系一元二次方程的求根公式\(x=-\dfrac{-b\pm\sqrt{b^2-4ac}}{2a}\),这里也是一......
  • 「KDOI-06-S」消除序列 题解
    分享一个应该很少人想到的做法。首先贪心地想,第一种操作肯定最多选择一次。比如如果选择了下标\(i\)和\(j\)进行第一种操作,那么就等价于在\(\max\{i,j\}\)进行了一次操作。由于代价是非负数,则我们最多只用执行一次。当然也可以不使用这种操作。有了这个思路,我们先考虑不使......
  • 「TAOI-2」Ciallo~(∠・ω< )⌒★ 题解
    手玩了一个小时终于做出来了,这不得写一篇题解记录一下??下面设\(s\)的长度为\(n\),\(t\)的长度为\(m\)。考虑分类讨论:如果\(s\)中有一个子串\(s'\)与\(t\)完全相同(可以用哈希进行比较),设\(s'\)是\(s\)的第\(l\)到第\(r\)个字符组成的字符串,则我们可以删除\([1,......
  • 三星G8 OLED显示器S34BG850SC,使用DP线连接电脑,显示器黑屏问题解决。
    这个问题在网上好像很多人问,但是每个人的情况不同,总之我也是遇到了。事情大概:PC机显卡的DP口通过显示器自带的MiniDP线和显示器相连,这个没什么好说的了,原配只送MiniDP线,想必买这台显示器的人都是先用的这根线。然而我有一台NUC,通过雷电口也连接到了这台显示器。所以我这台G8是......