[BZOJ4530][Bjoi2014]大融合(LCT)
2024-09-01 08:09:55
大佬们似乎都是用树剖+并查集优雅地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 ;
}
最新文章
- 基于jQuery的一个简单的图片查看器
- 通过HttpWebRequest请求https接口
- Memcached存储命令 - set
- [USACO2005][POJ2454]Jersey Politics(随机化)
- 小白日记25:kali渗透测试之提权(五)--利用配置不当提权
- tcpprep 对IPV6的支持
- DataTable操作(建表,建行,建列,添加数据)
- #include <;boost/bind.hpp>;
- WCF随笔3----消息编码器
- jQuery选择器(ID选择器)第一节
- n! 进制
- Do-Now—团队冲刺博客四
- SharePoint 2010 在同意匿名訪问的站点中隐藏登陆链接
- vue計算屬性
- HDU1251 字典树板子题
- JavaScript之BOM五大对象(window;location;navigator;screen;history)
- python之比较is与==(转载)
- linux下新建(mkdir)、删除(rmdir)文件夹
- 使用hibernate与mysql时数据不能插入的原因及解决办法
- python基础入门学习简单程序练习
热门文章
- Android 4.x 获取存储卡路径的方式
- 用java实现一个简易编译器
- 78. Subsets 求所有子集(有重复就continue)
- HowTo: Xen 4.1.3 Windows 8 HVM domU with Intel HD4000 VGA Passthrough on Debian Wheezy
- zookeeper会话超时 链接超时的排查
- c语言标准输入和scanf的关系
- 【转】The most comprehensive Data Science learning plan for 2017
- Ubuntu命令行下安装、卸载、管理软件包的方法
- 02 Transcribing DNA into RNA
- centos7.0查看有没有运行mysql