Description

有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: 输出所有节点中,权值最大的节点的权值

Input

输入的第一行是一个整数N,代表节点个数。

接下来一行输入N个整数,a[1], a[2], …, a[N],代表N个节点的初始权值。

再下一行输入一个整数Q,代表接下来的操作数。

最后输入Q行,每行的格式如题目描述所示。

Output

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

Sample Input

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

Sample Output

-10
10
10

HINT

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

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

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

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

Solution

第一眼:这不splay启发式合并板子题吗?
然后就开始漫长的写写写调调调
维护多颗splay
U:splay启发式合并,一个个删除小的splay插入到大的splay里面
A1:删除val[x],插入val[x]+v
A2:开个Add数组,维护每颗splay整体加的数
A3:搞个全局变量ALL记一下就好了
F1:直接输出val[x]+Add[x]+ALL
F2:直接输出Max[ID[x]],其中ID是x所属的平衡树编号
F3::这个相当于要维护Max[]的最大值。开个可删堆,每次Max[i]变化的时候就把旧的删掉,新的插入,F3查询的时候直接输出堆顶即可。
emmm话说为什么大部分人都写的堆啊_(Xз」∠)_

Code

 #include<iostream>
#include<cstdio>
#include<queue>
#define N (600000+1000)
using namespace std; int Son[N][],Father[N],Size[N];
int ID[N],Add[N],Val[N],Max[N];
int Root[N],n,m,x,y,v,ALL;
char opt[];
priority_queue<int>Heap,Del; int Get(int x){return Son[Father[x]][]==x;}
void Update(int x){Size[x]=Size[Son[x][]]+Size[Son[x][]]+;}
void Clear(int x){Son[x][]=Son[x][]=Father[x]=Size[x]=Val[x]=;} int Pre(int x)
{
x=Son[x][];
while (Son[x][]) x=Son[x][];
return x;
} int Get_Max(int x)
{
while (Son[x][]) x=Son[x][];
return Val[x];
} void Rotate(int x)
{
int wh=Get(x);
int fa=Father[x], fafa=Father[fa];
if (fafa) Son[fafa][Son[fafa][]==fa]=x;
Son[fa][wh]=Son[x][wh^]; Father[fa]=x;
if (Son[fa][wh]) Father[Son[fa][wh]]=fa;
Son[x][wh^]=fa; Father[x]=fafa;
Update(fa); Update(x);
} void Splay(int x)
{
for (int fa; (fa=Father[x]); Rotate(x))
if (Father[fa])
Rotate(Get(fa)==Get(x)?fa:x);
Root[ID[x]]=x;
} void Insert(int x,int y,int v)
{
int now=Root[ID[y]],fa=;
while ()
{
fa=now,now=Son[now][v>Val[now]];
if (now==)
{
Val[x]=v; Size[x]=; Father[x]=fa; ID[x]=ID[y];
Son[fa][v>Val[fa]]=x; Splay(x); return;
}
}
} void Delete(int x)
{
Splay(x);
if (!Son[Root[ID[x]]][] && !Son[Root[ID[x]]][])
{
Clear(Root[ID[x]]);
Root[ID[x]]=;
return;
}
if (!Son[Root[ID[x]]][])
{
Root[ID[x]]=Son[Root[ID[x]]][];
Clear(Father[Root[ID[x]]]);
Father[Root[ID[x]]]=;
return;
}
if (!Son[Root[ID[x]]][])
{
Root[ID[x]]=Son[Root[ID[x]]][];
Clear(Father[Root[ID[x]]]);
Father[Root[ID[x]]]=;
return;
}
int oldroot=Root[ID[x]];
int pre=Pre(Root[ID[x]]);
Splay(pre);
Son[Root[ID[x]]][]=Son[oldroot][];
Father[Son[oldroot][]]=Root[ID[x]];
Clear(oldroot);
Update(Root[ID[x]]);
} void Merge(int x,int y)
{
if (Son[x][]) Merge(Son[x][],y);
if (Son[x][]) Merge(Son[x][],y);
int val=Val[x]+Add[ID[x]]-Add[ID[y]]; Clear(x);
Insert(x,y,val);
} int main()
{
scanf("%d",&n);
for (int i=; i<=n; ++i)
{
scanf("%d",&x);
ID[i]=i; Val[i]=x; Max[i]=x;
Root[i]=i; Size[i]=; Heap.push(x);
}
scanf("%d",&m);
for (int i=; i<=m; ++i)
{
scanf("%s",opt);
if (opt[]=='U')
{
scanf("%d%d",&x,&y);
if (ID[x]!=ID[y])
{
Del.push(min(Max[ID[x]],Max[ID[y]]));
if (Size[Root[ID[x]]]>Size[Root[ID[y]]]) swap(x,y);
Max[ID[y]]=max(Max[ID[y]],Max[ID[x]]);
Merge(Root[ID[x]],Root[ID[y]]);
}
} if (opt[]=='A' && opt[]=='')
{
scanf("%d%d",&x,&v);
int val=Val[x]+v;
if (Size[Root[ID[x]]]==)
{
Val[x]=val;
Del.push(Max[ID[x]]);
Max[ID[x]]=val+Add[ID[x]];
Heap.push(Max[ID[x]]);
continue;
}
Delete(x); Insert(x,Root[ID[x]],val);
Del.push(Max[ID[x]]);
Max[ID[x]]=Get_Max(Root[ID[x]])+Add[ID[x]];
Heap.push(Max[ID[x]]);
} if (opt[]=='A' && opt[]=='')
{
scanf("%d%d",&x,&v), Add[ID[x]]+=v;
Del.push(Max[ID[x]]);
Max[ID[x]]=Get_Max(Root[ID[x]])+Add[ID[x]];
Heap.push(Max[ID[x]]);
} if (opt[]=='A' && opt[]=='')
scanf("%d",&v),ALL+=v; if (opt[]=='F' && opt[]=='')
scanf("%d",&x), printf("%d\n",Val[x]+Add[ID[x]]+ALL); if (opt[]=='F' && opt[]=='')
{
scanf("%d",&x), printf("%d\n",Max[ID[x]]+ALL);
} if (opt[]=='F' && opt[]=='')
{
while ((!Heap.empty()) && (!Del.empty()) && Heap.top()==Del.top())
Heap.pop(), Del.pop();
printf("%d\n",Heap.top()+ALL);
}
}
}

BZOJ2333:[SCOI2011]棘手的操作(Splay)的更多相关文章

  1. 真--可并堆模板--BZOJ2333: [SCOI2011]棘手的操作

    n<=300000个点,开始是独立的,m<=300000个操作: 方法一:单点修改.查询,区间修改.查询?等等等等这里修改是块修改不是连续的啊,那就让他连续呗!具体方法:离线后,每次连接两 ...

  2. BZOJ2333 [SCOI2011]棘手的操作 堆 左偏树 可并堆

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ2333 题意概括 有N个节点,标号从1到N,这N个节点一开始相互不连通.第i个节点的初始权值为a[i ...

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

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

  4. bzoj千题计划217:bzoj2333: [SCOI2011]棘手的操作

    http://www.lydsy.com/JudgeOnline/problem.php?id=2333 读入所有数据,先模拟一遍所有的合并操作 我们不关心联通块长什么样,只关心联通块内有谁 所以可以 ...

  5. 2019.01.17 bzoj2333: [SCOI2011]棘手的操作(启发式合并)

    传送门 启发式合并菜题. 题意:支持与连通块有关的几种操作. 要求支持连边,单点修改,连通块修改,全局修改和单点查值,连通块查最大值和全局最大值. 我们对每个连通块和答案用可删堆维护最大值,然后用启发 ...

  6. BZOJ2333 [SCOI2011]棘手的操作 【离线 + 线段树】

    题目 有N个节点,标号从1到N,这N个节点一开始相互不连通.第i个节点的初始权值为a[i],接下来有如下一些操作: U x y: 加一条边,连接第x个节点和第y个节点 A1 x v: 将第x个节点的权 ...

  7. bzoj2333 [SCOI2011]棘手的操作(洛谷3273)

    题目描述 有N个节点,标号从1到N,这N个节点一开始相互不连通.第i个节点的初始权值为a[i],接下来有如下一些操作:U x y: 加一条边,连接第x个节点和第y个节点A1 x v: 将第x个节点的权 ...

  8. bzoj2333 [SCOI2011]棘手的操作

    用set维护每个联通块里的最值,multiset维护所有块里的最值,并查集维护连通性,然后随便搞搞就行了,合并时候采用启发式合并.复杂度O(nlognlogn),大概勉强过的程度,反正跑的很慢就是了. ...

  9. (右偏树)Bzoj2333: [SCOI2011]棘手的操作

    题面 戳我 Sol 右偏树滑稽+并查集 再在全局开一个可删除的堆(priority_queue) 注意细节 # include <bits/stdc++.h> # define RG re ...

随机推荐

  1. jquery 文本框回车与change事件

    文本框的改变用change事件 要用bind,两个是有区别的,change只是在失去焦点的时候出发,很多时候不能满足需要.  代码如下   $('#flowfromid').bind("pr ...

  2. easyui焦点离开事件的解决方案

  3. CSS3新属性注释及实例

    这里把CSS3的新属性单独拿出来讲解一下: border-radius 属性用于创建圆角 div { border:2px solid; border-radius:25px; -moz-border ...

  4. Android-多线程Handler

    http://www.cnblogs.com/plokmju/p/android_Handler.html android不允许在主线程里做耗时操作,如网络操作,以此来避免ANR ANR(Applic ...

  5. Effective C++ .12 复制对象-拷贝构造函数的编写

    当我们自己编写拷贝构造函数时,编译器就不会为该类生成默认拷贝构造函数了,对于assignment operator也是如此. 1. 拷贝构造函数中记得调用父类的拷贝构造函数,或者相应复制过程 clas ...

  6. [翻译]Review——How to do Speech Recognition with Deep Learning

    原文地址:https://medium.com/@ageitgey/machine-learning-is-fun-part-6-how-to-do-speech-recognition-with-d ...

  7. js权威指南学习笔记(四)对象

    1.创建对象 (1).通过对象直接量的方式创建 说明:对象直接量是由若干名/值对组成的映射表,名/值对中间用冒号分隔,名/值对之间用逗号分隔,整个映射表用花括号括起来. 如:       5 5   ...

  8. Sencha Architect打开闪退问题修复

    删除以下位置的cache文件夹 C:\Users\Administrator\AppData\Local\Sencha\Sencha Architect 3.2\Cache bug解决参考 https ...

  9. 前端使用nginx上传文件时,进度获取不对

    在使用iview时,上传文件获取进度时onUploadProgress返回数据不对. 原因是开启了nginx代理,本地上传时先传到本地nginx然后在传到服务器,导致获取进度不对 解决:在nginx的 ...

  10. vue的事件

    vue的事件: vue事件简写: vue中事件是 v-on:click=' show()'    但是我嫌弃它写太长每次都要 v-on: 事件 vue中就有事件简写   @click='show()' ...