长链剖分 学习笔记

由于只做了一道题,并没有太深入的理解。主要为了养成写学习笔记的习惯吧,毕竟对很多基础的东西理解都不好。

概念

类似一般树剖的重链剖分,以子树的深度作为关键选出“长儿子”,可将树划分为若干条长链。考虑这样的优美性质:1.类似树剖可证明,每个点到根的路上最多经过 s q r t ( n ) sqrt(n) sqrt(n)条轻边;2.在计算以深度为下标的信息时,对每个点,若要合并它的所有儿子,只需直接继承它的重儿子,暴力合并它的轻儿子即可。这样,每个节点的信息只会在它向上第一个轻边贡献一次,在那之后的都算在它第一次合并到的长链上(因为比它长),所以复杂度时刻 O ( n ) O(n) O(n)的。

实现

容易用vector动态存储每个点的子树的信息,注意并不能同时保存每个点子树的信息(显然空间会炸),所以要求的值都在动态的计算过程中同时计算。
用指针的方式可以实现比较简便的存储,用一个指针数组保存每一个点子树的初始位置。

例题

DTOJ 1980. 谈笑风生(laugh)
题目链接

问题在于求一个点子树内和它距离不超过k的子树大小之和。
考虑对每一个点,用长链剖分求出子树内每个深度的节点的子树大小之和,并且需要做前缀和来回答询问。
但直接维护前缀和不好维护:每该一个深度,会影响到后面的深度。考虑改成维护后缀和,就消除了这样的影响。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=3e5+5;
int n,q,hd[N],to[N<<1],nx[N<<1],tt;
void add(int u,int v){
	nx[++tt]=hd[u]; to[hd[u]=tt]=v;
}
int fa[N],dp[N],sz[N],mx[N],sn[N];
ll tmp[N],*s[N],*id=tmp,ans[N];
void d1(int u){
	sz[u]=1; mx[u]=dp[u];
	for(int e=hd[u];e;e=nx[e]) if(to[e]!=fa[u]){
		int v=to[e]; fa[v]=u; dp[v]=dp[u]+1; d1(v);
		if(mx[v]>mx[sn[u]]) sn[u]=v;
		mx[u]=max(mx[u],mx[v]); sz[u]+=sz[v];
	}
}
struct node{
	int d,k;
};
vector<node>h[N];
void d2(int u){
	s[u][0]=sz[u]-1;
	if(sn[u]) s[sn[u]]=s[u]+1,d2(sn[u]);
	for(int e=hd[u];e;e=nx[e]){
		int v=to[e]; if(v==fa[u] || v==sn[u]) continue;
		s[v]=id; id+=mx[v]-dp[v]+1; d2(v);
		for(int i=0;i+dp[v]<=mx[v];i++) s[u][i+1]+=s[v][i];
	}
	s[u][0]+=s[u][1];
	int z=h[u].size();
	for(int i=0;i<z;i++){
		node x=h[u][i];
		ans[x.d]+=s[u][min(1,mx[u]-dp[u])]-((x.k>=mx[u]-dp[u])?0:s[u][x.k+1]);
	}
}
int main()
{
	cin>>n>>q;
	for(int u,v,i=1;i<n;i++) scanf("%d%d",&u,&v),add(u,v),add(v,u);
	dp[1]=1; d1(1);
	for(int i=1;i<=q;i++){
		int p,k; scanf("%d%d",&p,&k);
		ans[i]=1ll*min(dp[p]-1,k)*(sz[p]-1);
		h[p].push_back((node){i,k});
	}
	s[1]=id; id+=mx[1]-dp[1]+1; d2(1);
	for(int i=1;i<=q;i++) printf("%lld\n",ans[i]);
	return 0;
}
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、下载 4使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、 4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.m或d论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 、1资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
WebSocket 长连接指的是客户端与服务器之间建立的一种持久化的双向通信的连接。相比传统的 HTTP 连接,WebSocket 长连接具有以下优点: 1. 无需频繁建立连接和断开连接,减少了建立连接和断开连接的开销,提高了性能和效率; 2. 可以在客户端和服务器之间实时地双向传输数据,实现了真正意义上的实时通信; 3. WebSocket 长连接是基于 TCP 连接的,相比于 HTTP 连接,WebSocket 长连接更加稳定可靠。 在 C# 中,你可以使用 System.Net.WebSockets 命名空间提供的类来实现 WebSocket 长连接。具体实现方式可以参考以下代码: ``` using System; using System.Net.WebSockets; using System.Threading; using System.Threading.Tasks; public class WebSocketExample { public static async Task Connect(string uri) { ClientWebSocket webSocket = null; try { webSocket = new ClientWebSocket(); await webSocket.ConnectAsync(new Uri(uri), CancellationToken.None); Console.WriteLine("WebSocket connected!"); await Task.WhenAll(Receive(webSocket), Send(webSocket)); } catch (Exception ex) { Console.WriteLine($"Exception: {ex.Message}"); } finally { webSocket?.Dispose(); Console.WriteLine("WebSocket disconnected!"); } } private static async Task Send(ClientWebSocket webSocket) { while (webSocket.State == WebSocketState.Open) { string message = Console.ReadLine(); byte[] bytes = System.Text.Encoding.UTF8.GetBytes(message); await webSocket.SendAsync(new ArraySegment<byte>(bytes), WebSocketMessageType.Text, true, CancellationToken.None); } } private static async Task Receive(ClientWebSocket webSocket) { byte[] buffer = new byte[1024]; while (webSocket.State == WebSocketState.Open) { var result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None); if (result.MessageType == WebSocketMessageType.Text) { string message = System.Text.Encoding.UTF8.GetString(buffer, 0, result.Count); Console.WriteLine($"Received message: {message}"); } } } } ``` 以上代码实现了一个简单的客户端,通过 Connect 方法连接到指定的 WebSocket 服务器,并实现了发送和接收数据的功能。如果你想要实现 WebSocket 服务器端,你可以使用 System.Net.WebSockets 命名空间提供的类来实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值