题目大意:有$n(n\leqslant2\times10^5)$个序列,有$m(m\leqslant2\times10^5)$个操作,分三种:

1. $M\;x\;y:$把$x$所在的序列放在$y$所在序列之后
2. $D\;x:$把$x$所在的序列从它前面断开
3. $Q\;x\;y:$询问若$x,y$在同一序列中,它们之间的元素和

题解:平衡树,合并就正常合并,注意是把$x$放到$y$后,关于找$x$所在的序列,就记录每个节点的父亲,直接向上跳父亲就可以了,在分裂时注意维护父亲。

求元素的排名就看一下它是不是它父亲的右儿子,是的话把它兄弟的大小加上。

询问就记录一个区间和即可。

卡点:

C++ Code:

#include <algorithm>
#include <cstdio>
#include <cstdlib>
#define maxn 200010 namespace Treap {
int pri[maxn], lc[maxn], rc[maxn], fa[maxn], sz[maxn], V[maxn];
long long S[maxn];
int ta, tb, tmp, res;
inline void nw(int pos, int x) {
pri[pos] = rand();
S[pos] = V[pos] = x;
lc[pos] = rc[pos] = fa[pos] = 0;
sz[pos] = 1;
}
inline int update(int rt) {
const int lc = Treap::lc[rt], rc = Treap::rc[rt];
if (lc) fa[lc] = rt;
if (rc) fa[rc] = rt;
sz[rt] = sz[lc] + sz[rc] + 1;
S[rt] = S[lc] + S[rc] + V[rt];
return rt;
}
void split(int rt, int k, int &x, int &y) {
if (!rt) x = y = 0;
else {
if (sz[lc[rt]] >= k) {
split(lc[rt], k, x, lc[rt]);
fa[x] = fa[rt] = 0;
y = update(rt);
} else {
split(rc[rt], k - sz[lc[rt]] - 1, rc[rt], y);
fa[rt] = fa[y] = 0;
x = update(rt);
}
}
}
int merge(int x, int y) {
if (!x || !y) return x | y;
if (pri[x] < pri[y]) { rc[x] = merge(rc[x], y); return update(x); }
else { lc[y] = merge(x, lc[y]); return update(y); }
}
inline int gtrnk(int x) {
res = sz[lc[x]] + 1;
while (x) {
if (rc[fa[x]] == x) res += sz[lc[fa[x]]] + 1;
x = fa[x];
}
return res;
}
inline int gtrt(int x) {
while (fa[x]) x = fa[x];
return x;
} inline void Merge(int x, int y) {
x = gtrt(x), y = gtrt(y);
if (x == y) return ;
merge(y, x);
}
inline void Split(int x) {
int rk = gtrnk(x); x = gtrt(x);
split(x, rk - 1, ta, tb);
}
inline void query(int x, int y) {
int root = gtrt(x);
if (root != gtrt(y)) {
puts("-1");
return ;
}
int rkx = gtrnk(x), rky = gtrnk(y);
if (rkx > rky) std::swap(rkx, rky);
split(root, rky, ta, tb);
split(ta, rkx - 1, ta, tmp);
printf("%lld\n", S[tmp]);
merge(ta, merge(tmp, tb));
}
} int n, m; int main() {
srand(20040826);
scanf("%d%d", &n, &m);
for (int i = 1, x; i <= n; ++i) {
scanf("%d", &x);
Treap::nw(i, x);
}
while (m --> 0) {
char op;
int x, y;
scanf("%1s%d", &op, &x);
switch (op) {
case 'M':
scanf("%d", &y);
Treap::Merge(x, y);
break;
case 'D':
Treap::Split(x);
break;
case 'Q':
scanf("%d", &y);
Treap::query(x, y);
}
}
return 0;
}

  

[洛谷P4847]银河英雄传说V2的更多相关文章

  1. P4847 银河英雄传说V2 题解(Splay)

    题目链接 P4847 银河英雄传说V2 解题思路 我天哪!!!\(splay\)在\(rotate\)的时候先\(upd(y)\)再\(upd(x)\)!!以后不能再因为这个\(WA\)一晚上了!!! ...

  2. NOI2002 洛谷 P1196 银河英雄传说

    神奇的并查集问题 题目描述 公元五八○一年,地球居民迁移至金牛座α第二行星,在那里发表银河联邦 创立宣言,同年改元为宇宙历元年,并开始向银河系深处拓展. 宇宙历七九九年,银河系的两大军事集团在巴米利恩 ...

  3. 洛谷—— P1196 银河英雄传说

    https://www.luogu.org/problem/show?pid=1196 题目描述 公元五八○一年,地球居民迁至金牛座α第二行星,在那里发表银河联邦创立宣言,同年改元为宇宙历元年,并开始 ...

  4. 洛谷 [p1196] 银河英雄传说

    所谓带权并查集 本题所求的不止是两个编号之间是否有关系,还要求两个编号之间有什么关系,这就要求我们维护多个数组,fa[]数组维护两个编号之间的连通性,dis[]维护编号为i的战舰到fa[i]之间的距离 ...

  5. 洛谷P1196 银河英雄传说

    大意:你有30000个队列,第i个队列中只有i 有T个操作,1,把某个队列头接到另一个队列尾. 2,问两个元素之间的距离. 本题主要有三种解法. ①带权并查集. 具体来说就是,并查集维护当前集合的大小 ...

  6. NOI2002_ Galaxy银河英雄传说86

    NOI2002_ Galaxy银河英雄传说86     公元五八○一年,地球居民迁移至金牛座α第二行星,:宇宙历七九九年,银河系的两大军事集团在巴米利恩星:杨威利擅长排兵布阵,巧妙运用各种战术屡次以少 ...

  7. NOI2002 银河英雄传说

    P1196 银河英雄传说 367通过 1.1K提交 题目提供者该用户不存在 标签并查集NOI系列2001(或之前) 难度提高+/省选- 提交该题 讨论 题解 记录 最新讨论 莱因哈特什么鬼? 私人代码 ...

  8. [洛谷P1338] 末日的传说

    洛谷题目链接:末日的传说 题目描述 只要是参加jsoi活动的同学一定都听说过Hanoi塔的传说:三根柱子上的金片每天被移动一次,当所有的金片都被移完之后,世界末日也就随之降临了. 在古老东方的幻想乡, ...

  9. 加权并查集(银河英雄传说,Cube Stacking)

    洛谷P1196 银河英雄传说 题目描述 公元五八○一年,地球居民迁移至金牛座α第二行星,在那里发表银河联邦创立宣言,同年改元为宇宙历元年,并开始向银河系深处拓展.宇宙历七九九年,银河系的两大军事集团在 ...

随机推荐

  1. spring之HttpInvoker

    一.HttpInvoker是常用的Java同构系统之间方法调用实现方案,是众多Spring项目中的一个子项目.顾名思义,它通过HTTP通信即可实现两个Java系统之间的远程方法调用,使得系统之间的通信 ...

  2. 海思NB-IOT的SDK看门狗的使用

    1. 看门狗需要喂狗,如果自己写的任务一直运行,那么空闲任务无法运行会导致看门狗复位,来看下看门狗的机制,首先系统启动的时候创建了空闲任务 在这个函数里面void vTaskStartSchedule ...

  3. javasript 字符串 数组操作

    Javascript中经常涉及到对字符串和数组的处理,今天总结一下具体的用法 一 操作字符串 String对象有很多函数,可以以不同的方式访问和操作字符串,具体方法如下:   charAt(index ...

  4. Qt-QML-QML调用C++类

    QML用来做界面,在不考虑数据的请款下,那是溜溜的,但是,程序是没有不和后台数据交互的,但是了,QML在数据处理方面的效率又是不敢恭维的,这里就出现了QML负责前端界面,而后端使用JS或者C++了. ...

  5. JavaScript基本概念(1)-声明提升

    声明提升: function > var > other var提升的时候,只是声明提升,但是赋值还是会在原来的位置. Javascript Hoisting:In javascript, ...

  6. 推荐:一个适合于Python新手的入门练手项目

    随着人工智能的兴起,国内掀起了一股Python学习热潮,入门级编程语言,大多选择Python,有经验的程序员,也开始学习Python,正所谓是人生苦短,我用Python 有个Python入门练手项目, ...

  7. 关于javascript的一个小问题,请问有人看出啥问题吗?

    最近学习javascript,有一个问题挺奇怪的,先贴出代码: function binarySearch(){ var arr = [0,1,2,3]; var res = actbinarySea ...

  8. ubuntu samba配置注意事项

    1. 下载samba前, ubuntu镜像源需要更新为国内源,否则samba的安装会非常慢 亲测,清华的镜像源速度满足要求. A.登录 https://mirrors.tuna.tsinghua.ed ...

  9. Docker容器的搭建

    Docker容器的搭建 一.先从Docker Hub上面拉取一个基础镜像 命令:docker pull ubuntu 命令说明:pull:拉取镜像的命令,ubuntu:拉取镜像的名称 扩展命令: 命令 ...

  10. 贵州省未来二十年的投资机会的探讨2>

    房产投资 升值最快的 在教育资源丰富  生活方便的 地方 价格和地段取其中之一. 其次 车位 再其次墓地等 公寓住房. 还有商标 和网站注册 公司注册 除了以上的这些  还有茅台生效酒 收藏