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. Centos 从零开始 (二)

    因为我是搞 nodejs的 所以以后会安装一些依赖于node的 比如mongodb数据库等. 6:安装nodejs 安装的时候遇到个小问题.yum install nodejs 报错 说没有这个包.然 ...

  2. Java - 关于扩展线程安全类的一些思考

    重用可以节省我们进行开发和测试(测试比我们自己测严谨地多)的时间和其他各种成本. 但是,对一个线程安全类进行扩展的时候就需要思考一些问题. 比如我们熟知的线程安全类Vector,该类中对所有的公有方法 ...

  3. Sequence contains no elements : LINQ error

    1.错误意思: 出现错误的原因是:你要从一个null中取的数据. 2.错误的处理 1,使用FirstOrDefault() 来代替 First() 2.使用SingleOrDefault 来代替 Si ...

  4. .net core 填坑记之—格式转换问题

    最近在将项目从.net 迁移到.net core环境中,迁移完成后,发布于Windows平台上进行测试,所有功能均能正常运行. 为了项目能够在正式环境也能正常运行,提前进行Linux环境部署(Cent ...

  5. Cheatsheet: 2017 03.01 ~ 03.31

    Web New Year, New Blog Day 10 - Using JetBrains Rider with a .NET Core Console Application JavaScrip ...

  6. [转]ubuntu 13.04 体验wine qq

    1.首先安装最新版的wine1.52,没记错版本号应该是这个 sudo add-apt-repository ppa:ubuntu-wine/ppa sudo apt-get update sudo ...

  7. Windows安装配置xampp

    建议大家直接看原文 1.安装XAMPP 进入https://www.apachefriends.org/zh_cn/index.html页面下载XAMPP 2 3.打开xampp控制版 4.修改apa ...

  8. python使用元类

    原文:https://blog.csdn.net/youzhouliu/article/details/51906158 type() 动态语言和静态语言最大的不同,就是函数和类的定义,不是编译时定义 ...

  9. 快速数组对象取值与数组映射新数组--array.map

    array.map(callback,[ thisObject]); 1.map方法的作用不难理解,“映射”嘛,也就是原数组被“映射”成对应新数组 a)array.map(()=>值); [1, ...

  10. easyui grid 里的可编辑text 加清空图标

    $.extend($.fn.datagrid.defaults.editors, { text: { init: function (container, options) { var _opt = ...