题目传送门

棘手的操作

题目描述

有N个节点,标号从1到N,这N个节点一开始相互不连通。第i个节点的初始权值为a[i],接下来有如下一些操作:

  • U x y: 加一条边,连接第x个节点和第y个节点
  • A1 x v: 将第x个节点的权值增加v
  • A2 x v: 将第x个节点所在的连通块的所有节点的权值都增加v
  • A3 v: 将所有节点的权值都增加v
  • F1 x: 输出第x个节点当前的权值
  • F2 x: 输出第x个节点所在的连通块中,权值最大的节点的权值
  • F3: 输出所有节点中,权值最大的节点的权值

输入输出格式

输入格式:

输入的第一行是一个整数N,代表节点个数。接下来一行输入N个整数,a[1], a[2], ..., a[N],代表N个节点的初始权值。再下一行输入一个整数Q,代表接下来的操作数。最后输入Q行,每行的格式如题目描述所示。

输出格式:

对于操作F1, F2, F3,输出对应的结果,每个结果占一行。

输入输出样例

输入样例#1:

3
0 0 0
8
A1 3 -20
A1 2 20
U 1 3
A2 1 10
F1 3
F2 3
A3 -10
F3

输出样例#1:

-10
10
10

说明

对于30%的数据,保证 N<=100,Q<=10000

对于80%的数据,保证 N<=100000,Q<=100000

对于100%的数据,保证 N<=300000,Q<=300000

对于所有的数据,保证输入合法,并且 -1000<=v, a[1], a[2], ..., a[N]<=1000


  分析:

  真是一道恶心的左偏树题。

  需要维护两个左偏树,第一个维护正常的操作信息,第二个维护所有点中的最大值。

  第一种操作:在第一个左偏树中$merge$即可,另外有一个小优化,合并的两个堆顶中较小的一个可以直接从第二个左偏树中删除(正确性自己思考)。

  第二种操作:将该点从两个左偏树中删除,修改值以后再重新放回去。

  第三种操作:用$lazy$标记,只修改堆顶的值,后面再$merge$或者删除节点的时候下方标记。

  第四种操作:用一个变量记录,需要输出的时候再加上。

  第五种操作:直接输出第一个左偏树中该节点的值。

  第六种操作:直接输出第一个左偏树中该节点所在堆的堆顶的值。

  第七种操作:直接输出第二个左偏树的根节点的值。

  以上。

  题如其名,真$TM$又棘手又恶心。。。

  Code:

//It is made by HolseLee on 28th Aug 2018
//Luogu.org P3273
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define Max(a,b) (a)>(b) ? (a) : (b)
using namespace std;const int N=3e5+7;
int n,a[N],m,allsign,root;
struct Leftist{int ch[N][2],val[N],sign[N],fa[N],dis[N];void clear(int x){ch[x][0]=ch[x][1]=fa[x]=0;}int sum(int x){int ret=0;while(x=fa[x])ret+=sign[x];return ret;}void pushdown(int x){int ul=ch[x][0], ur=ch[x][1];if( ul )val[ul]+=sign[x], sign[ul]+=sign[x];if( ur )val[ur]+=sign[x], sign[ur]+=sign[x];sign[x]=0;}int merge(int x,int y){if(!x||!y)return x+y;if( val[x]<val[y] )swap(x,y);pushdown(x);int &ul=ch[x][0], &ur=ch[x][1];ur=merge(ur,y); fa[ur]=x;if( dis[ur]>dis[ul] )swap(ul,ur);dis[x]=dis[ur]+1;return x;}int find(int x){while(fa[x])x=fa[x];return x;}int delet(int x){pushdown(x);int fx=fa[x];int ka=merge(ch[x][0],ch[x][1]);fa[ka]=fx;if( fx )ch[fx][x==ch[fx][1]]=ka;while( fx ) {if( dis[ch[fx][0]]<dis[ch[fx][1]] )swap(ch[fx][0],ch[fx][1]);if( dis[fx]==dis[ch[fx][1]]+1 )return root;dis[fx]=dis[ch[fx][1]]+1;ka=fx;fx=fa[fx];}return ka;}int add_point(int x,int v){int fx=find(x);if( fx==x ) {if( ch[x][0]+ch[x][1]==0 ){val[x]+=v; return x;} else {if( ch[x][0] ) fx=ch[x][0];else fx=ch[x][1];}}delet(x);val[x]+=v+sum(x);clear(x);return merge(find(fx),x);}int build(){queue<int>t;for(int i=1; i<=n; ++i) t.push(i);int x,y,z;while( t.size()>1 ) {x=t.front(); t.pop();y=t.front(); t.pop();z=merge(x,y);t.push(z);}return t.front();}
}T,H;void read(int &x)
{x=0; char ch=getchar(); bool flag=false;while( ch<'0' || ch>'9' ) {if( ch=='-' )flag=true;ch=getchar();}while( ch>='0' && ch<='9' ) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}flag?x*=(-1):1;
}int main()
{read(n);T.dis[0]=H.dis[0]=-1;for(int i=1; i<=n; ++i){read(a[i]);T.val[i]=H.val[i]=a[i];}root=H.build();read(m);char op[3];int x,y,fx,fy,temp;for(int i=1; i<=m; ++i){scanf("%s",op);if( op[0]=='A' ) {switch( op[1] ){case '1':read(x), read(y);root=H.delet(T.find(x));temp=T.add_point(x,y);H.val[temp]=T.val[temp];H.clear(temp);root=H.merge(root,temp);break;case '2':read(x), read(y); fx=T.find(x);root=H.delet(fx);T.val[fx]+=y; T.sign[fx]+=y;H.val[fx]=T.val[fx];H.clear(fx);root=H.merge(root,fx);break;case '3':read(y);allsign+=y;break;}} else if( op[0]=='F' ) {switch( op[1] ){case '1':read(x);printf("%d\n",T.val[x]+allsign+T.sum(x));break;case '2':read(x);printf("%d\n",T.val[T.find(x)]+allsign);break;case '3':printf("%d\n",H.val[root]+allsign);break;}} else {read(x), read(y);fx=T.find(x), fy=T.find(y);if( fx==fy )continue;temp=T.merge(fx,fy);if( temp==fx )root=H.delet(fy);else root=H.delet(fx);}}return 0;
}

转载于:https://www.cnblogs.com/cytus/p/9551080.html

洛谷P3273 [SCOI2011] 棘手的操作 [左偏树]相关推荐

  1. 洛谷P4971:断罪者(左偏树)

    解析 看起来就是左偏树的基本操作啊- 然而就是调不过去 吐了qwq 参考了望月大神的实现 感觉清晰的多 就定义并查集维护的是每个点所在的堆的根节点 一下子少了很多恶心的套娃 代码 #include&l ...

  2. YBTOJ洛谷P4331:数字序列(左偏树)

    文章目录 题目描述 数据范围 解析 代码 题目描述 数据范围 n<=1e6n<=1e6n<=1e6 解析 先考虑简单情况 如果原数列是单调递增的,显然应该使bi=aib_i=a_ib ...

  3. 洛谷P3261 [JLOI2015]城池攻占(左偏树)

    传送门 每一个城市代表的点开一个小根堆,把每一个骑士合并到它开始攻占的城池所代表的点上 然后开始dfs,每一次把子树里那些还活着的骑士合并上来 然后再考虑当前点的堆,一直pop直到骑士全死光或者剩下的 ...

  4. 【学习笔记】浅谈短小可爱的左偏树(可并堆)

    文章目录 左偏树 左偏树的合并(merge)操作 例题 罗马游戏 [Apio2012]dispatching [JLOI2015]城池攻占 [Baltic2004]sequence 左偏树 左偏树是一 ...

  5. 【左偏树】【bzoj 2333】: [SCOI2011]棘手的操作

    http://www.lydsy.com/JudgeOnline/problem.php?id=2333 带lazy的左偏树,由于我不会写,所以借(chao)鉴(xi)了一下hzwer #includ ...

  6. 左偏树初步学习 洛谷P3377

    玩的有点多......睡的有点少... 左偏树是一种支持O(logn)的时间复杂度内进行合并的堆式数据结构. 定义: 外结点:左儿子或者右儿子是空结点的结点 距离:一个结点x的距离disx定义为其子树 ...

  7. [bzoj2333] [SCOI2011]棘手的操作 (可并堆)

    //以后为了凑字数还是把题面搬上来吧2333 发布时间果然各种应景... Time Limit: 10 Sec  Memory Limit: 128 MB Description 有N个节点,标号从1 ...

  8. 【BZOJ】2333: [SCOI2011]棘手的操作

    http://www.lydsy.com/JudgeOnline/problem.php?id=2333 题意: 有N个节点,标号从1到N,这N个节点一开始相互不连通.第i个节点的初始权值为a[i], ...

  9. 【洛谷3377】 左偏树(可并堆)

    前言 其实我是不小心翻线性基的时候看见的. Solution 左偏树只会模板,挖坑待补 代码实现 #include<stdio.h> #include<stdlib.h> #i ...

最新文章

  1. 《Pro ASP.NET MVC 3 Framework》学习笔记之九【Ninject的使用-下】
  2. Contest Hunter CH6201 走廊泼水节 最小生成树 Kruskal
  3. 计算机二级c语言题型2018,计算机二级C语言题型和评分标准
  4. 排序算法系列:Shell 排序算法
  5. kie-api_7.0上的新KIE持久性API
  6. php开发工具 debug,php开发性能调试工具xdebug
  7. 鸿蒙系统对手机性能的提升,鸿蒙OS手机版再爆新特性,流畅度和性能大幅提升,用户评价很高...
  8. 快手上也可以看电竞赛事了:S9直播观看人数惊人!
  9. Java面试知识(持续更新)
  10. kubernetes存储系统介绍(Volume、PV、dynamic provisioning,阿里云服务器nfs创建pv,hostpath创建pv)
  11. Alibaba秋招前端测试题
  12. redux之createStore
  13. C语言基础—进制转换
  14. 2022-2028中国安全代码审查软件市场现状研究分析与发展前景预测报告
  15. Oracle 中文排序 Oracle 中文字段排序
  16. php文字下划线,如何在文字下面添加下划线
  17. CoordinatorLayout布局和自定义Behavior
  18. oracle中 greatest、east、coalesce
  19. cURL error 77: error setting certificate verify locations: CAfile: d:\cacert.pem CApath: none (see h
  20. Python官网主页改版 http://www.python.org/

热门文章

  1. mysql5.7乱码_mysql5.7中解决中文乱码的问题
  2. 计算机一级应用于段落还是文字,计算机一级复习资料
  3. c语言箭头指针的作用,C语言中,结构体成员变量的点和箭头
  4. batchplot插件用法_Batchplot批量打印怎么用?Batchplot批量打印教程
  5. 三个彩灯循环点亮程序_近百组彩灯点亮江畔,义渡灯会正式亮灯啦
  6. 《MySQL——备库多线程复制策略。》
  7. 简单的数据增强代码(C++与opencv)
  8. c++ cdi+示例_C ++'not'关键字和示例
  9. Java Character.UnicodeBlock of()方法与示例
  10. 在计算机领域客观事物的属性表示为数据,数据与信息试题解析