大融合
小强要在 个孤立的星球上建立起一套通信系统。这套通信系统就是连接 个点的一个树。这个树的边是一条一条添加上去的。在某个时刻,一条边的负载就是它所在的当前能够联通的树上路过它的简单路径的数量。

例如,在上图中,现在一共有五条边。其中, 这条边的负载是 ,因为有六条简单路径 路过了 。
现在,你的任务就是随着边的添加,动态的回答小强对于某些边的负载的询问。
Solution
题目求的是一条边两侧子树大小之积。支持插边。
那么可以考虑lct。
有个问题:lct不能维护子树信息。
那么我们可以对于一个点,把实儿子和虚儿子分开维护,还有一个总的信息。
总信息=实儿子的总信息+虚儿子的信息+本身的信息。
要改的只有link和access。

1 #include<cstdio> 2 #include<iostream> 3 #include<cstdlib> 4 #include<cstring> 5 #include<algorithm> 6 #include<cmath> 7 #define maxn 100005 8 using namespace std; 9 int n,q,t1,t2; 10 struct node{ 11 int f,ch[2],sum,sx,sy;//sum ×ÜºÍ sx ʵ×ÓÊ÷ sy Ðé×ÓÊ÷ 12 int re; 13 }tr[maxn]; 14 void wh(int x){ 15 int ls=tr[x].ch[0],rs=tr[x].ch[1]; 16 tr[x].sum=tr[ls].sum+tr[rs].sum+tr[x].sy+1; 17 } 18 int zh[maxn],top; 19 void upv(int x){ 20 if(!x)return; 21 tr[x].re^=1; 22 swap(tr[x].ch[0],tr[x].ch[1]); 23 } 24 void down(int x){ 25 if(tr[x].re){ 26 upv(tr[x].ch[0]);upv(tr[x].ch[1]); 27 tr[x].re=0; 28 } 29 } 30 int get(int x){ 31 return tr[tr[x].f].ch[1]==x; 32 } 33 bool isroot(int x){ 34 return tr[tr[x].f].ch[0]!=x&&tr[tr[x].f].ch[1]!=x; 35 } 36 37 void rotate(int x){ 38 int y=tr[x].f,z=tr[y].f; 39 int wx=get(x),wy=get(y); 40 if(!isroot(y))tr[z].ch[wy]=x;tr[x].f=z; 41 tr[y].ch[wx]=tr[x].ch[wx^1];tr[tr[x].ch[wx^1]].f=y; 42 tr[x].ch[wx^1]=y;tr[y].f=x; 43 wh(y);wh(x); 44 } 45 void splay(int x){ 46 int y=x;top=0; 47 for(;!isroot(y);y=tr[y].f)zh[++top]=y;zh[++top]=y; 48 while(top)down(zh[top--]); 49 while(!isroot(x)){ 50 y=tr[x].f; 51 if(!isroot(y))rotate(get(y)==get(x)?y:x); 52 rotate(x); 53 } 54 } 55 void access(int x){ 56 for(int y=0;x;y=x,x=tr[x].f){ 57 splay(x); 58 tr[x].sy+=tr[tr[x].ch[1]].sum; 59 tr[x].ch[1]=y; 60 tr[x].sy-=tr[y].sum; 61 wh(x); 62 } 63 } 64 void makeroot(int x){ 65 access(x);splay(x); 66 upv(x);wh(x); 67 } 68 void link(int x,int y){ 69 makeroot(x);makeroot(y); 70 tr[x].f=y; 71 tr[y].sy+=tr[x].sum;wh(y); 72 } 73 void split(int x,int y){ 74 makeroot(x); 75 access(y);splay(y); 76 } 77 long long ask(int x,int y){ 78 split(x,y); 79 int s1=tr[x].sum,s2=tr[y].sum-s1; 80 81 return 1LL*s1*s2; 82 } 83 int main() 84 { 85 cin>>n>>q; 86 for(int i=1;i<=n;i++)tr[i].sum=1; 87 while(q--){ 88 char ch;scanf(" %c",&ch); 89 scanf("%d%d",&t1,&t2); 90 if(ch=='A')link(t1,t2); 91 else printf("%lld\n",ask(t1,t2)); 92 } 93 return 0; 94 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构