题目

题目链接

题意

给出nnn个整数,其中1≤n≤106" role="presentation" style="position: relative;">1≤n≤1061≤n≤1061≤n≤10^6。
给出三种操作:

  • GROW x y,表示给xxx位置的数增加y" role="presentation" style="position: relative;">yyy。
  • MAGIC x,表示给所有的数增加xxx。
  • CUT x,表示把所有大于x的数切割到x,并输出本次切割割了多少。

题解

乍一看,似乎没有很符合这个题目情形的数据结构,我们需要把多种数据结构结合起来。

首先我们把所有的数值相同的元素都归并到一起(采用并查集的方法),并在这一个集合中找出一个关键的点(并查集的根节点)扔到平衡树里面去,平衡树的第一关键字是该并查集所具有的值,第二关键字是该并查集的根节点。

在这个基础下,GROW x y操作就相当于把x处的元素从它所在并查集中拆出来,拆成一个独立的点,然后给这个点的值加y,再把修改后的元素放入起所在的并查集中去。
时间复杂度:O(log(n))" role="presentation" style="position: relative;">O(log(n))O(log(n))O(log(n))

MAGIC x操作就直接记录一个累加hhh就好了,在查询的时候用到。
时间复杂度:O(1)" role="presentation" style="position: relative;">O(1)O(1)O(1)

CUT x操作就相当于在平衡树中,找到所有的值大于等于x-h的并查集,计算好贡献以后,把所有的这些找到的并查集合并成为一个并查集,并且该并查集的值为x-h。

时间复杂度:O(两次CUT之间的操作数)O(两次CUT之间的操作数)O(两次CUT之间的操作数)

复杂度计算如果不对,请评论告知我。

注意

  1. 在这道题中并查集还应该记录一个属性,就是并查集的大小。
  2. 该并查集支持元素从并查集中剥离,因此需要为每个元素设置一个盒子,即idaidaida数组,当一个元素被剥离的时候,给元素一个新的盒子,原来的并查集结构保持不变,但是要求原来并查集的大小-1。

代码

#include <iostream>
#include <cstdio>
#include <set>
#define pr(x) cout<<#x<<":"<<x<<endl
#define int long long
using namespace std;
typedef pair<int,int> pii;
const int maxn = 2e6;
int pa[maxn],sz[maxn];
void init(){ for(int i = 1;i < maxn;++i) pa[i] = i,sz[i] = 1;}
int find(int x){ return x == pa[x]?x:pa[x] = find(pa[x]);}
void join(int x,int y){int px = find(x),py = find(y);if(px != py) { pa[px] = py; sz[py] += sz[px];}
}
set<pii> st;
int id,ida[maxn],n,q,h,tmp,a[maxn];
char op[6];
void ins(int pid){auto it = st.lower_bound(make_pair(a[pid],0));if(it == st.end() || it->first != a[pid]) st.insert(make_pair(a[pid],pid));else join(pid,it->second);
}
int split(int pos){int pid = find(ida[pos]);  if(sz[pid] == 1) st.erase(st.find(make_pair(a[pid],pid)));else {sz[pid] --;ida[pos] = ++id;a[id] = a[pid];}return pid;
}
main()
{init();id = 0;scanf("%lld%lld",&n,&q);for(int i = 1;i <= n;++i) {scanf("%lld",&tmp);ida[i] = ++id;a[id] = tmp;ins(id);}while(q--){scanf("%s",op);if(*op == 'G'){int pos,x;scanf("%lld%lld",&pos,&x);int nid = split(pos);a[nid] += x;ins(nid);}else if(*op == 'M'){int x;scanf("%lld",&x);h += x;}else if(*op == 'C'){int x;scanf("%lld",&x);int ans = 0;auto it = st.lower_bound(make_pair(x-h,0));if(it == st.end()) {printf("0\n");continue;}pii p = make_pair(x-h,it->second);ans += (it->first+h-x)*sz[it->second];a[it->second] = x-h;int pid = it->second;it = st.erase(it);while(it != st.end()){ans += (it->first-x+h)*sz[it->second];join(it->second,pid);it = st.erase(it);}st.insert(p);printf("%lld\n",ans);}}return 0;
}

codeforces gym-101736 Farmer Faul 平衡树+并查集相关推荐

  1. gym:Problem A Artwork(并查集思维题)

    20162017-acmicpc-nordic-collegiate-programming-contest-ncpc-2016 Problem A Artwork 题目链接 http://codef ...

  2. CodeForces - 755C PolandBall and Forest (并查集)

    题意:给定n个数,Ai的下标为1~n.对于每一个i,Ai与i在同一个树上,且是与i最远的点中id最小的点(这个条件变相的说明i与Ai连通).求森林中树的个数. 分析:若i与Ai连通,则在同一个树上,因 ...

  3. CodeForces - 722C Destroying Array(倒着并查集+离线处理)

    题目链接:点击查看 题目大意:给出一个数列a,现在给出操作b,每次操作都会删除掉数列a中指定位置的数,问每次删除后,最大连续字段和是多少 题目分析:一开始看到最大连续字段和,以为是要用dp,又看了一下 ...

  4. CF思维联系--CodeForces - 218C E - Ice Skating (并查集)

    题目地址:24道CF的DIv2 CD题有兴趣可以做一下. ACM思维题训练集合 Bajtek is learning to skate on ice. He's a beginner, so his ...

  5. 【CodeForces - 722C】Destroying Array(并查集,时光倒流)

    题干: 给定一个有n个数的序列a1,a2, ..., an 你每次可以将序列中一个数删去,剩下的数会被分割为一段一段连续的数列 给定一个删除数的顺序,问在每次删除之后,剩下的连续的数列中,数列和的最大 ...

  6. 【CodeForces - 357C 】Knight Tournament(并查集 或 STLset)

    题干: Hooray! Berl II, the king of Berland is making a knight tournament. The king has already sent th ...

  7. Codeforces 827D Best Edge Weight 倍增 + 并查集 || 倍增 + 压倍增标记 (看题解)

    Best Edge Weight 我们先找出一棵最小生成树, 对于非树边来说, 答案就是两点路径上的最大值 - 1, 这个直接倍增就能处理. 对于树边来说, 就是非树边的路径经过这条边的最小值 - 1 ...

  8. codeforces 892E(离散化+可撤销并查集)

    题意 给出一个n个点m条边的无向联通图(n,m<=5e5),有q(q<=5e5)个询问 每个询问询问一个边集{Ei},回答这些边能否在同一个最小生成树中 分析 要知道一个性质,就是权值不同 ...

  9. Codeforces.1051G.Distinctification(线段树合并 并查集)

    题目链接 \(Description\) 给定\(n\)个数对\(A_i,B_i\).你可以进行任意次以下两种操作: 选择一个位置\(i\),令\(A_i=A_i+1\),花费\(B_i\).必须存在 ...

最新文章

  1. linux 下 vi 块编辑
  2. oracle中怎样查询用户权限
  3. 机器学习一 -- 什么是监督学习和无监督学习?
  4. python打开另一个程序_python 新手问题啊,为什么我运行一个python程序,另一个就会自动退出呢?始终只能运行一个...
  5. QT的QStackedLayout
  6. Dorado Debugger工具
  7. PAT:1050. String Subtraction (20) AC
  8. 25岁房贷上万濒临失业,大专小哥转行软件测试“挽救”人生
  9. python查看mongo库容量_mongo查看数据库空间大小
  10. 指针与指针指向的内容(四)
  11. Google Docs API 发布,自动化文档处理
  12. Qi v1.2.4协议 之 11 Foreign Object Detection 【英文翻译】
  13. WEB专用服务器的安全设置
  14. android实战:密码箱三
  15. 数据分析三大神器之三:matplotlib
  16. 关于Hanlp的源码
  17. 扒一扒那些叫欧拉的定理们(一)——基本介绍和简单多面体欧拉定理
  18. 多次 ifconfig down 无效的问题
  19. cPanel/WHM前台后台的常用操作
  20. 基于51单片机蜂鸣器的音乐播放器设计C

热门文章

  1. iphone4 base64 mp3 无法解析 html5,javascript - 如何使用HTML5在firefox上播放base64音频数据? - 堆栈内存溢出...
  2. 计算机函数公式中怎么合并合并,Excel用函数和公式瞬间实现把表格全部合并到一个表中去...
  3. 你可能对position和z-index有一些误解
  4. Facade(外观)--对象结构型模式
  5. SpringCloud常见问题总结(一)
  6. 线性代数---矩阵的各种问题求解方法
  7. 数据结构 旅游规划(Dijkstra+Dfs)
  8. 清明梦超能力者黄YY、异或树(线段树合并)
  9. P3733 [HAOI2017]八纵八横(线性基/线段树分治)
  10. hdu 1521 排列组合 多重集排列 + 指数生成函数