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) ...
随机推荐
- 使用vuex实现父组件调用子组件方法
曲线救国. 核心原理就是父子共用一个vuex对象,且看代码: 父组件parent.vue <template> <div class="wrap"> < ...
- 窥探原理:实现一个简单的前端代码打包器 Roid
roid roid 是一个极其简单的打包软件,使用 node.js 开发而成,看完本文,你可以实现一个非常简单的,但是又有实际用途的前端代码打包工具. 如果不想看教程,直接看代码的(全部注释):点击地 ...
- 51NOD 1277 字符串中的最大值(KMP)
>>点击进入原题测试<< 思路:用KMP优化的暴力写了一遍,超时!没有充分利用KMP中next数组的性质. 首先这个题是肯定要用到KMP算法的,然后会有一个next[]数组. ...
- [bzoj3191][JLOI2013][卡牌游戏] (概率dp)
Description N个人坐成一圈玩游戏.一开始我们把所有玩家按顺时针从1到N编号.首先第一回合是玩家1作为庄家.每个回合庄家都会随机(即按相等的概率)从卡牌堆里选择一张卡片,假设卡片上的数字 ...
- 九九乘法表-Java
public class Test1 { public static void main(String[] args){ for(int i=1;i<=9;i++){ for(int j=1;j ...
- Spring核心技术(一)——IoC容器和Bean简介
IoC容器和Bean简介 这章包括了Spring框架对于IoC规则的实现.Ioc也同DI(依赖注入).而对象是通过构造函数,工厂方法,或者一些Set方法来定义对象之间的依赖的.容器在创建这些Bean对 ...
- 【Codeforces 466B】Wonder Room
[链接] 我是链接,点我呀:) [题意] 让你把长为a,宽为b的房间扩大(长和宽都能扩大). 使得它的面积达到6*n 问你最小的能满足要求的面积是多少 输出对应的a和b [题解] 假设a< b ...
- Java中list集合ArrayList 中contains包含的使用
Java中list集合ArrayList 中contains包含的使用 https://blog.csdn.net/qq_38556611/article/details/78774690
- [bzoj2657][Zjoi2012]旅游 journey_ 对偶图_树形dp
旅游 bzoj-2657 Zjoi-2012 题目大意:题目链接 注释:$1\le K\le 2\cdot 10^5$. 想法:这题... 感觉和上一个题的提示有些类似,就是题目生怕你不知道这是一道对 ...
- Ubuntu 16.04设置文件夹试图永久以列表显示
图片来自:http://forum.ubuntu.org.cn/viewtopic.php?p=2043385