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

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

题目描述

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

现在,你的任务就是随着边的添加,动态的回答小强对于某些边的负载的 询问。

输入输出格式

输入格式:

 

第一行包含两个整数 N, Q ,表示星球的数量和操作的数量。星球从 1 开始编号。

接下来的 Q 行,每行是如下两种格式之一:

  • A x y 表示在 x 和 y 之间连一条边。保证之前 x 和 y 是不联通的。
  • Q x y表示询问 (x,y) 这条边上的负载。保证 x 和 y 之间有一条边。

 

输出格式:

 

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

 

输入输出样例

输入样例#1: 
8 6A 2 3A 3 4A 3 8A 8 7A 6 5Q 3 8
输出样例#1: 
6

说明

对于所有数据,1≤N,Q≤1000000

 

 

玄学LCT。。。。

首先根据我的常识一般的LCT是不能维护子树的,,,如果要的话好像得用一个叫top_tree的玩意。。。

但这个题需要维护的子树信息太简单了所以可以直接用LCT维护子树。

具体的说,子树有实有虚,一般的LCT只能维护实子树的信息(也就是重链)。

对于本题来说,我们多加一个数组son[x]表示x的虚子树的siz和。

然后发现只有树中的轻重边变化或者树的形态变化的时候才会影响到siz和son。

例如ACCESS,LINK,CUT。

讨论一下就好了。

 

#include
#define ll long long#define maxn 1000005using namespace std;struct LCT{ int f[maxn],ch[maxn][2]; int siz[maxn],son[maxn]; int tag[maxn],q[maxn],tp; int n,m,uu,vv; char cr; inline int get(int x){ return ch[f[x]][1]==x; } inline bool isroot(int x){ return (ch[f[x]][0]!=x&&ch[f[x]][1]!=x); } inline void pushdown(int x){ if(tag[x]){ tag[x]=0,swap(ch[x][0],ch[x][1]); tag[ch[x][0]]^=1,tag[ch[x][1]]^=1; } } inline void update(int x){ siz[x]=1+siz[ch[x][0]]+siz[ch[x][1]]+son[x]; } inline void rotate(int x){ int fa=f[x],ffa=f[fa],tp=get(x); ch[fa][tp]=ch[x][tp^1],f[ch[fa][tp]]=fa; ch[x][tp^1]=fa,f[fa]=x; f[x]=ffa; if(ch[ffa][1]==fa||ch[ffa][0]==fa) ch[ffa][ch[ffa][1]==fa]=x; update(fa),update(x); } inline void splay(int x){ tp=0; for(int i=x;;i=f[i]){ q[++tp]=i; if(isroot(i)) break; } for(;tp;tp--) pushdown(q[tp]); for(;!isroot(x);rotate(x)) if(!isroot(f[x])) rotate(get(f[x])==get(x)?f[x]:x); } inline void access(int x){ for(int t=0;x;t=x,x=f[x]){ splay(x); son[x]+=siz[ch[x][1]]-siz[t]; ch[x][1]=t,update(x); } } inline void makeroot(int x){ access(x),splay(x); tag[x]^=1; } inline void link(int x,int y){ makeroot(x),access(y),splay(y); f[x]=y,son[y]+=siz[x],update(y); } inline void solve(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) siz[i]=1; while(m--){ cr=getchar(); while(cr!='A'&&cr!='Q') cr=getchar(); scanf("%d%d",&uu,&vv); if(cr=='A') link(uu,vv); else{ makeroot(uu); access(vv),splay(vv); printf("%lld\n",(ll)(siz[uu])*(ll)(siz[vv]-siz[uu])); } } }}mine;int main(){ mine.solve(); return 0;}

  

转载于:https://www.cnblogs.com/JYYHH/p/8425236.html

你可能感兴趣的文章
《网络攻防》第二周作业
查看>>
关于Windows Live Writer博客同步
查看>>
linux下的C语言快速学习—计算机体系结构基础简单了解
查看>>
nextTick refs
查看>>
内置函数
查看>>
ucore lab1实验笔记
查看>>
java内部类概念
查看>>
(60)zabbix网络发现介绍Network Discovery
查看>>
annotation本质
查看>>
shell之文本过滤(awk)
查看>>
学习进度条--第五周
查看>>
获取spring中所有的bean名称
查看>>
linux常用命令
查看>>
java DecimalFormat
查看>>
简单两步快速学会使用Mybatis-Generator自动生成entity实体、dao接口和简单mapper映射(用mysql和oracle举例)...
查看>>
Spring读书笔记-----Spring核心机制:依赖注入
查看>>
如何挂载阿里云的数据盘
查看>>
block extends include三者的差别跟用法
查看>>
服务器安全
查看>>
系统学习qsort1 尤其partition
查看>>