传送门

大佬们似乎都是用树剖+并查集优雅地A了此题

然后我太弱了,只能打打LCT的板子

虽然的确可以挺无脑的A掉……

不过至少这题教了我该怎么维护LCT上虚子树的信息,具体看这里

首先,答案很明显是断开边后两个子树的大小之积

所以只要把这条边split出来,答案就是$(size[y]-size[x])*size[x]$(很好理解)

或者$x的虚子树大小*y的虚子树大小$(我用的是这种方法,为什么的话,代码里有注解)

 //minamoto
#include<cstdio>
#include<algorithm>
#include<iostream>
#define ll long long
using namespace std;
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[<<],*p1=buf,*p2=buf;
inline int read(){
#define num ch-'0'
char ch;bool flag=;int res;
while(!isdigit(ch=getc()))
(ch=='-')&&(flag=true);
for(res=num;isdigit(ch=getc());res=res*+num);
(flag)&&(res=-res);
#undef num
return res;
}
char obuf[<<],*o=obuf;
inline void print(ll x){
if(x>) print(x/);
*o++=x%+;
}
const int N=;
int fa[N],ch[N][],s[N],rev[N],top,sum[N],summ[N];
inline bool isroot(int x){return ch[fa[x]][]!=x&&ch[fa[x]][]!=x;}
inline void pushup(int x){sum[x]=sum[ch[x][]]+sum[ch[x][]]+summ[x]+;}
inline void pushdown(int x){
if(x&&rev[x]){
swap(ch[x][],ch[x][]);
rev[ch[x][]]^=,rev[ch[x][]]^=;
rev[x]=;
}
}
void rotate(int x){
int y=fa[x],z=fa[y],d=ch[y][]==x;
if(!isroot(y)) ch[z][ch[z][]==y]=x;
fa[x]=z,fa[y]=x,fa[ch[x][d^]]=y,ch[y][d]=ch[x][d^],ch[x][d^]=y,pushup(y);
}
void splay(int x){
s[top=]=x;for(int i=x;!isroot(i);i=fa[i]) s[++top]=fa[i];
while(top) pushdown(s[top--]);
for(int y=fa[x],z=fa[y];!isroot(x);y=fa[x],z=fa[y]){
if(!isroot(y))
((ch[y][]==x)^(ch[z][]==y))?rotate(x):rotate(y);
rotate(x);
}
pushup(x);
}
inline void access(int x){
for(int y=;x;x=fa[y=x])
splay(x),summ[x]+=sum[ch[x][]],summ[x]-=sum[ch[x][]=y];
}
inline void makeroot(int x){
access(x),splay(x),rev[x]^=;
}
inline void split(int x,int y){
makeroot(x),access(y),splay(y);
}
inline void link(int x,int y){
split(x,y),summ[fa[x]=y]+=sum[x],pushup(y);
}
int main(){
//freopen("testdata.in","r",stdin);
int n=read(),m=read();
for(int i=;i<=n;++i) sum[i]=;
while(m--){
char ch;int u,v;
ch=getc(),u=read(),v=read();
if(ch=='A') link(u,v);
else split(u,v),print(1ll*(summ[u]+)*(summ[v]+)),*o++='\n';
/*split之后splay中肯定只有u,v两点
然后虚子树中的点数就相当于cut之后两点各自的子树大小
然后又因为u和v都已经被splay过了,肯定没有点在它上面*/
}
fwrite(obuf,o-obuf,,stdout);
return ;
}

最新文章

  1. 基于jQuery的一个简单的图片查看器
  2. 通过HttpWebRequest请求https接口
  3. Memcached存储命令 - set
  4. [USACO2005][POJ2454]Jersey Politics(随机化)
  5. 小白日记25:kali渗透测试之提权(五)--利用配置不当提权
  6. tcpprep 对IPV6的支持
  7. DataTable操作(建表,建行,建列,添加数据)
  8. #include &lt;boost/bind.hpp&gt;
  9. WCF随笔3----消息编码器
  10. jQuery选择器(ID选择器)第一节
  11. n! 进制
  12. Do-Now—团队冲刺博客四
  13. SharePoint 2010 在同意匿名訪问的站点中隐藏登陆链接
  14. vue計算屬性
  15. HDU1251 字典树板子题
  16. JavaScript之BOM五大对象(window;location;navigator;screen;history)
  17. python之比较is与==(转载)
  18. linux下新建(mkdir)、删除(rmdir)文件夹
  19. 使用hibernate与mysql时数据不能插入的原因及解决办法
  20. python基础入门学习简单程序练习

热门文章

  1. Android 4.x 获取存储卡路径的方式
  2. 用java实现一个简易编译器
  3. 78. Subsets 求所有子集(有重复就continue)
  4. HowTo: Xen 4.1.3 Windows 8 HVM domU with Intel HD4000 VGA Passthrough on Debian Wheezy
  5. zookeeper会话超时 链接超时的排查
  6. c语言标准输入和scanf的关系
  7. 【转】The most comprehensive Data Science learning plan for 2017
  8. Ubuntu命令行下安装、卸载、管理软件包的方法
  9. 02 Transcribing DNA into RNA
  10. centos7.0查看有没有运行mysql