长链剖分

类似于重链剖分,我们将一棵树分成多条重链。
对于每个点,其重儿子(也可以称为长儿子)是到叶子节点距离最远的点。
然后类似于静态链分治,我们在计算某个点的答案时先计算重儿子,然后直接继承重儿子答案,再暴力合并轻儿子答案。
为了实现空间与时间复杂的的降低,我们需要用指针来实现。
长链剖分的时间复杂度为\(O(n)\)
考虑每条重链,仅会在其链顶被暴力合并一次、
而重链的长度总和为\(O(n)\)
所以复杂度为\(O(n)\)
例题:CF1009F Dominant Indices
首先这题有一个非常显然的\(dp\)
\(f_{u,i}\)\(u\)的子树中深度为\(i\)的点的个数,\(S_u\)\(u\)的子树。
那么\(f_{u,0}=1,f_{u,i}=\sum\limits_{v\in S_u}f_{v,i-1}\)
然后我们考虑长链剖分,并且把\(f\)开成指针数组。
对于重儿子,我们直接指针赋一下值,答案加个一即可。
对于轻儿子,我们暴力合并。
实现过程中,我们开一个长度为\(n\)的tmp\(数组,每条长链分配\)len_u\((\)u$是这条长链的顶点)的空间,具体用指针实现。

#include<bits/stdc++.h>
#define pb push_back
using namespace std;
namespace IO
{
    char ibuf[(1<<21)+1],obuf[(1<<21)+1],st[15],*iS,*iT,*oS=obuf,*oT=obuf+(1<<21);
    char Get(){return (iS==iT? (iT=(iS=ibuf)+fread(ibuf,1,(1<<21)+1,stdin),(iS==iT? EOF:*iS++)):*iS++);}
    void Flush(){fwrite(obuf,1,oS-obuf,stdout),oS=obuf;}
    void Put(char x){*oS++=x;if(oS==oT)Flush();}
    int read(){int x=0;char ch=Get();while(ch>57||ch<48)ch=Get();while(ch>=48&&ch<=57)x=x*10+(ch^48),ch=Get();return x;}
    void write(int x){int top=0;if(!x)Put('0');while(x)st[++top]=(x%10)+48,x/=10;while(top)Put(st[top--]);Put('\n');}
}
using namespace IO;
const int N=1000007;
vector<int>G[N];
int len[N],son[N],t[N],*f[N],*id=t,ans[N],n;
void dfs(int u,int fa)
{
    for(int v:G[u]) if(v^fa) dfs(v,u),son[u]=len[v]>len[son[u]]? v:son[u];
    len[u]=len[son[u]]+1;
}
void dp(int u,int fa)
{
    f[u][0]=1;
    if(son[u]) f[son[u]]=f[u]+1,dp(son[u],u),ans[u]=ans[son[u]]+1;
    for(int v:G[u])
    {
        if(v==fa||v==son[u]) continue;
        f[v]=id,id+=len[v],dp(v,u);
        for(int j=1;j<=len[v];++j)
    {
            f[u][j]+=f[v][j-1];
            if((j<ans[u]&&f[u][j]>=f[u][ans[u]])||(j>ans[u]&&f[u][j]>f[u][ans[u]])) ans[u]=j;
        }
    }
    if(f[u][ans[u]]==1) ans[u]=0;
}
int main()
{
    n=read();int i,u,v;
    for(i=1;i<n;++i) u=read(),v=read(),G[u].pb(v),G[v].pb(u);
    dfs(1,0),f[1]=id,id+=len[1],dp(1,0);
    for(i=1;i<=n;++i) write(ans[i]);
    return Flush(),0;
}

转载于:https://www.cnblogs.com/cjoierShiina-Mashiro/p/11561305.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
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、付费专栏及课程。

余额充值