博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[Bjoi2014]大融合
阅读量:6306 次
发布时间:2019-06-22

本文共 2531 字,大约阅读时间需要 8 分钟。

[Bjoi2014]大融合

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 394  Solved: 244
[][][]

Description

小强要在N个孤立的星球上建立起一套通信系统。这套通信系统就是连接N个点的一个树。
这个树的边是一条一条添加上去的。在某个时刻,一条边的负载就是它所在的当前能够
联通的树上路过它的简单路径的数量。
例如,在上图中,现在一共有了5条边。其中,(3,8)这条边的负载是6,因
为有六条简单路径2-3-8,2-3-8-7,3-8,3-8-7,4-3-8,4-3-8-7路过了(3,8)。
现在,你的任务就是随着边的添加,动态的回答小强对于某些边的负载的
询问。

Input

第一行包含两个整数N,Q,表示星球的数量和操作的数量。星球从1开始编号。
接下来的Q行,每行是如下两种格式之一:
A x y 表示在x和y之间连一条边。保证之前x和y是不联通的。
Q x y 表示询问(x,y)这条边上的负载。保证x和y之间有一条边。
1≤N,Q≤100000

Output

对每个查询操作,输出被查询的边的负载。

Sample Input

8 6
A 2 3
A 3 4
A 3 8
A 8 7
A 6 5
Q 3 8

Sample Output

6
LCT维护子树信息
维护两个和,sum:总的和(虚边+实边),cnt:虚边和
需要修改的操作:
access:cnt+=sum[ch[x][1]]-sum[t]  x原来的实边变为虚边,加上他,t由虚边变为实边,减去他
link:x练到y上,x的子树全部成为y的虚子树,所以cnt[y]+=sum[x]
#include
#include
#include
using namespace std;#define N 1000001int ch[N][2],fa[N],sum[N],st[N],top,cnt[N];bool tag[N];struct LCT{ bool isroot(int x) { return ch[fa[x]][0]!=x && ch[fa[x]][1]!=x;} void update(int x) { sum[x]=1+cnt[x]+sum[ch[x][0]]+sum[ch[x][1]]; } int getson(int x) { return ch[fa[x]][1]==x; } void down(int x) { if(tag[x]) { tag[x]^=1; tag[ch[x][0]]^=1; tag[ch[x][1]]^=1; swap(ch[x][0],ch[x][1]); } } void rotate(int x) { int y=fa[x],z=fa[y],l=getson(x),r=l^1; if(!isroot(y)) ch[z][ch[z][1]==y]=x; ch[y][l]=ch[x][r]; ch[x][r]=y; fa[x]=z; fa[y]=x; fa[ch[y][l]]=y; update(y); } void splay(int x) { st[top=1]=x; for(int i=x;!isroot(i);i=fa[i]) st[++top]=fa[i]; for(int i=top;i;i--) down(st[i]); while(!isroot(x)) { int y=fa[x]; if(!isroot(y)) rotate(getson(x)==getson(y) ? y : x); rotate(x); } update(x); } void access(int x) { int t=0; while(x) { splay(x); cnt[x]+=sum[ch[x][1]]-sum[t]; ch[x][1]=t; update(x); t=x; x=fa[x]; } } void make_root(int x) { access(x); splay(x); tag[x]^=1; } void split(int x,int y) { make_root(x); access(y); splay(y); } void link(int x,int y) { split(x,y); cnt[y]+=sum[x]; fa[x]=y; update(y);}};LCT lct;int main(){ int n,m; scanf("%d%d",&n,&m); fill(sum+1,sum+n+1,1); char s[2]; int x,y; while(m--) { scanf("%s%d%d",s,&x,&y); if(s[0]=='A') lct.link(x,y); else lct.split(x,y),printf("%lld\n",1ll*sum[x]*(sum[y]-sum[x])); }}

 

转载于:https://www.cnblogs.com/TheRoadToTheGold/p/7106520.html

你可能感兴趣的文章
rails 字符串 转化为 html
查看>>
java-学习8
查看>>
AOP动态代理
查看>>
Oracle序列
查看>>
xcodebuild命令行编译错误问题解决
查看>>
Yii2.0 下的 load() 方法的使用
查看>>
华为畅玩5 (CUN-AL00) 刷入第三方twrp Recovery 及 root
查看>>
LeetCode----67. Add Binary(java)
查看>>
母版页 MasterPage
查看>>
[转] ReactNative Animated动画详解
查看>>
DNS原理及其解析过程
查看>>
记录自写AFNetWorking封装类
查看>>
没想到cnblog也有月经贴,其实C#值不值钱不重要。
查看>>
【转】LUA内存分析
查看>>
springboot使用schedule定时任务
查看>>
[转] Entity Framework Query Samples for PostgreSQL
查看>>
XDUOJ 1115
查看>>
PHP学习(四)---PHP与数据库MySql
查看>>
模版方法模式--实现的capp流程创建与管理
查看>>
软件需求分析的重要性
查看>>