BZOJ 4530 LCT/线段树合并
//By SiriusRen
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=;
int n,q,cnt,dfn[N],last[N],tree[N*],lson[N*],rson[N*];
int first[N],next[N],v[N],w[N],tot,root[N],fa[N],deep[N],f[N];
struct Node{int xx,yy;char op[];}node[N];
void dfs(int x){
dfn[x]=++cnt;
for(int i=first[x];~i;i=next[i])
if(v[i]!=fa[x])deep[v[i]]=deep[x]+,fa[v[i]]=x,dfs(v[i]);
last[x]=cnt;
}
void add(int x,int y){v[tot]=y,next[tot]=first[x],first[x]=tot++;}
void Add(int x,int y){add(x,y),add(y,x);}
void insert(int l,int r,int &pos,int num,int wei){
if(!pos)pos=++cnt;
if(l==r){tree[pos]=wei;return;}
int mid=(l+r)>>;
if(mid<num)insert(mid+,r,rson[pos],num,wei);
else insert(l,mid,lson[pos],num,wei);
tree[pos]=tree[lson[pos]]+tree[rson[pos]];
}
int query(int l,int r,int pos,int L,int R){
if(!pos)return ;
if(l>=L&&r<=R)return tree[pos];
int mid=(l+r)>>;
if(mid<L)return query(mid+,r,rson[pos],L,R);
else if(mid>=R)return query(l,mid,lson[pos],L,R);
else return query(l,mid,lson[pos],L,R)+query(mid+,r,rson[pos],L,R);
}
void merge(int pos1,int &pos2){
if(!pos2)pos2=++cnt;
tree[pos2]+=tree[pos1];
// printf("pos1=%d pos2=%d lson[pos1]=%d rson[pos1]=%d tree[pos]=%d\n",pos1,pos2,lson[pos1],rson[pos1],tree[pos2]);
if(lson[pos1])merge(lson[pos1],lson[pos2]);
if(rson[pos1])merge(rson[pos1],rson[pos2]);
}
int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
void dfs2(int x){
if(lson[x])dfs2(lson[x]);
if(rson[x])dfs2(rson[x]);
}
int main(){
memset(first,-,sizeof(first));
scanf("%d%d",&n,&q),getchar();
for(int i=;i<=q;i++){
scanf("%s%d%d",node[i].op,&node[i].xx,&node[i].yy);
if(node[i].op[]=='A')Add(node[i].xx,node[i].yy);
}
for(int i=;i<=n;i++)if(!fa[i])dfs(i);
cnt=;
for(int i=;i<=n;i++)insert(,n,root[i],dfn[i],),f[i]=i;
for(int i=;i<=q;i++){
if(node[i].op[]=='A'){
int fx=find(node[i].xx),fy=find(node[i].yy);
if(fx!=fy)merge(root[fx],root[fy]),f[fx]=fy;
}
else{
if(deep[node[i].xx]>deep[node[i].yy])swap(node[i].xx,node[i].yy);
int fy=find(node[i].yy);
long long temp=query(,n,root[fy],dfn[node[i].yy],last[node[i].yy]);
printf("%lld\n",(tree[root[fy]]-temp)*temp);
}
}
}
//By SiriusRen
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=;
int n,m,xx,yy,fa[N],ch[N][],rev[N],size[N],Size[N],q[N],top;
char op[];
bool isroot(int x){return ch[fa[x]][]!=x&&ch[fa[x]][]!=x;}
void push_up(int x){size[x]=size[ch[x][]]+size[ch[x][]]++Size[x];}
void push_down(int x){if(rev[x])rev[ch[x][]]^=,rev[ch[x][]]^=,swap(ch[x][],ch[x][]),rev[x]=;}
void rotate(int p){
int q=fa[p],y=fa[q],x=(ch[q][]==p);
ch[q][x]=ch[p][!x],fa[ch[q][x]]=q;
ch[p][!x]=q,fa[p]=y;
if(!isroot(q)){
if(ch[y][]==q)ch[y][]=p;
if(ch[y][]==q)ch[y][]=p;
}fa[q]=p,push_up(q);
}
void splay(int x){
q[++top]=x;
for(int i=x;!isroot(i);i=fa[i])q[++top]=fa[i];
while(top)push_down(q[top]),top--;
for(int y=fa[x];!isroot(x);rotate(x),y=fa[x])if(!isroot(y)){
if((ch[fa[y]][]==y)^(ch[y][]==x))rotate(x);
else rotate(y);
}push_up(x);
}
void access(int x){for(int t=;x;t=x,x=fa[x])splay(x),Size[x]+=size[ch[x][]]-size[t],ch[x][]=t,push_up(x);}
void makeroot(int x){access(x),splay(x),rev[x]^=;}
void link(int x,int y){makeroot(x),makeroot(y),fa[x]=y,Size[y]+=size[x],push_up(y);}
void split(int x,int y){makeroot(x),access(y),splay(x);}
int main(){
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)size[i]=;
while(m--){
scanf("%s%d%d",op,&xx,&yy);
if(op[]=='A')link(xx,yy);
else split(xx,yy),printf("%lld\n",1ll*(Size[yy]+)*(size[xx]-Size[yy]-));
}
}
BZOJ 4530 LCT/线段树合并的更多相关文章
- BZOJ #5457: 城市 [线段树合并]
线段树合并的板子题,每次从下到上合并就完事了 // by Isaunoya #include <bits/stdc++.h> using namespace std; #define re ...
- BZOJ 3779 LCT 线段树 DFS序 坑
hhhh抄了半天lty代码最后T了 对拍也没事.. 药丸 mine #pragma GCC optimize("O3") //By SiriusRen #include < ...
- [BZOJ 2212] [Poi2011] Tree Rotations 【线段树合并】
题目链接:BZOJ - 2212 题目分析 子树 x 内的逆序对个数为 :x 左子树内的逆序对个数 + x 右子树内的逆序对个数 + 跨越 x 左子树与右子树的逆序对. 左右子树内部的逆序对与是否交换 ...
- BZOJ.4399.魔法少女LJJ(线段树合并)
BZOJ 注意\(c\leq7\)→_→ 然后就是裸的权值线段树+线段树合并了. 对于取\(\max/\min\)操作可以直接区间修改清空超出范围的值,然后更新到对应位置上就行了(比如对\(v\)取\ ...
- BZOJ.5461.[PKUWC2018]Minimax(DP 线段树合并)
BZOJ LOJ 令\(f[i][j]\)表示以\(i\)为根的子树,权值\(j\)作为根节点的概率. 设\(i\)的两棵子树分别为\(x,y\),记\(p_a\)表示\(f[x][a]\),\(p_ ...
- BZOJ.3307.雨天的尾巴(dsu on tree/线段树合并)
BZOJ 洛谷 \(dsu\ on\ tree\).(线段树合并的做法也挺显然不写了) 如果没写过\(dsu\)可以看这里. 对修改操作做一下差分放到对应点上,就成了求每个点子树内出现次数最多的颜色, ...
- BZOJ.3653.谈笑风生(长链剖分/线段树合并/树状数组)
BZOJ 洛谷 \(Description\) 给定一棵树,每次询问给定\(p,k\),求满足\(p,a\)都是\(b\)的祖先,且\(p,a\)距离不超过\(k\)的三元组\(p,a,b\)个数. ...
- BZOJ.5417.[NOI2018]你的名字(后缀自动机 线段树合并)
LOJ 洛谷 BZOJ 考虑\(l=1,r=|S|\)的情况: 对\(S\)串建SAM,\(T\)在上面匹配,可以得到每个位置\(i\)的后缀的最长匹配长度\(mx[i]\). 因为要去重,对\(T\ ...
- BZOJ 3277 串 & BZOJ 3473 字符串 (广义后缀自动机、时间复杂度分析、启发式合并、线段树合并、主席树)
标签那么长是因为做法太多了... 题目链接: (bzoj 3277) https://www.lydsy.com/JudgeOnline/problem.php?id=3277 (bzoj 3473) ...
随机推荐
- (一)python条件语句和基本数据类型
条件语句 语法一:if...else if <条件成立>: 处理过程 else: 处理过程 语法二:if...elif...else if <条件1成立>: 处理过程1 el ...
- python文件读写及形式转化和CGI的简单应用
一丶python文件读写学习笔记 open() 将会返回一个 file 对象,基本语法格式如下: open(filename, mode) filename:包含了你要访问的文件名称的字符串值. mo ...
- 洛谷 2476 [SCOI2008]着色方案
50%的数据满足:1 <= k <= 5, 1 <= ci <= 3 100%的数据满足:1 <= k <= 15, 1 <= ci <= 5 [题解] ...
- saltstack(四) saltstack的targeting、分组
targeting支持如下matcher: Globing : '*', 正则: 指定-E参数,正则表达式匹配多个 List: 指定-L参数,salt -E 'web1-(prod|devel)' t ...
- go 语言学习指南(一)
参考资料: http://www.runoob.com/go/go-tutorial.html
- ansible roles例子
#理解 changed_when failed_when become become_user ansible_become ansible_become_user static #检查group_v ...
- 将Jquery EasyUI中DataGird的数据导入Excel中
1.第一步获取前台DataGrid中的数据 var rows = $('#tb).datagrid("getRows"); if (rows.length = ...
- 【BZOJ3676&UOJ103】回文串(manacher,Trie)
题意:考虑一个只包含小写拉丁字母的字符串s.我们定义s的一个子串t的“出现值”为t在s中的出现次数乘以t的长度. 请你求出s的所有回文子串中的最大出现值. len<=300000 思路:鸣谢UO ...
- 【eclipse】eclipse启动优化&打印GC信息&重要的堆结构连接
eclipse启动优化,终于不那么卡了! 网上找了好多都是myEclipse的优化的,跟eclipse有点区别,找了很多方法还是不能让这个eclipse(Version: Kepler Release ...
- android调试
要进行调试,首先构建app的时候必须选择是Debug模式,而不能是Release模式. 接下来的内容转载自: http://www.cnblogs.com/gaoteng/p/5711314.html ...