题目传送门

棘手的操作

题目描述

有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+;
int n,a[N],m,allsign,root;
struct Leftist{
int ch[N][],val[N],sign[N],fa[N],dis[N]; void clear(int x)
{
ch[x][]=ch[x][]=fa[x]=;
} int sum(int x)
{
int ret=;
while(x=fa[x])ret+=sign[x];
return ret;
} void pushdown(int x)
{
int ul=ch[x][], ur=ch[x][];
if( ul )val[ul]+=sign[x], sign[ul]+=sign[x];
if( ur )val[ur]+=sign[x], sign[ur]+=sign[x];
sign[x]=;
} 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][], &ur=ch[x][];
ur=merge(ur,y); fa[ur]=x;
if( dis[ur]>dis[ul] )swap(ul,ur);
dis[x]=dis[ur]+;
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][],ch[x][]);
fa[ka]=fx;
if( fx )ch[fx][x==ch[fx][]]=ka;
while( fx ) {
if( dis[ch[fx][]]<dis[ch[fx][]] )
swap(ch[fx][],ch[fx][]);
if( dis[fx]==dis[ch[fx][]]+ )
return root;
dis[fx]=dis[ch[fx][]]+;
ka=fx;
fx=fa[fx];
}
return ka;
} int add_point(int x,int v)
{
int fx=find(x);
if( fx==x ) {
if( ch[x][]+ch[x][]== ){
val[x]+=v; return x;
} else {
if( ch[x][] ) fx=ch[x][];
else fx=ch[x][];
}
}
delet(x);
val[x]+=v+sum(x);
clear(x);
return merge(find(fx),x);
} int build()
{
queue<int>t;
for(int i=; i<=n; ++i) t.push(i);
int x,y,z;
while( t.size()> ) {
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=; char ch=getchar(); bool flag=false;
while( ch<'' || ch>'' ) {
if( ch=='-' )flag=true;
ch=getchar();
}
while( ch>='' && ch<='' ) {
x=(x<<)+(x<<)+(ch^);
ch=getchar();
}
flag?x*=(-):;
} int main()
{
read(n);
T.dis[]=H.dis[]=-;
for(int i=; i<=n; ++i){
read(a[i]);
T.val[i]=H.val[i]=a[i];
}
root=H.build();
read(m);
char op[];int x,y,fx,fy,temp;
for(int i=; i<=m; ++i){
scanf("%s",op);
if( op[]=='A' ) {
switch( op[] ){
case '':
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 '':
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 '':
read(y);
allsign+=y;
break;
}
} else if( op[]=='F' ) {
switch( op[] ){
case '':
read(x);
printf("%d\n",T.val[x]+allsign+T.sum(x));
break; case '':
read(x);
printf("%d\n",T.val[T.find(x)]+allsign);
break; case '':
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 ;
}

洛谷P3273 [SCOI2011] 棘手的操作 [左偏树]的更多相关文章

  1. 洛谷.3273.[SCOI2011]棘手的操作(左偏树)

    题目链接 还是80分,不是很懂. /* 七个操作(用左偏树)(t2表示第二棵子树): 1.合并:直接合并(需要将一个t2中原有的根节点删掉) 2.单点加:把这个点从它的堆里删了,加了再插入回去(有负数 ...

  2. bzoj2333[SCOI2011]棘手的操作 洛谷P3273 [SCOI2011]棘手的操作

    2333? 先记一下吧,这题现在全部都是照着题解做的,因为怎么改都改不出来,只好对着题解改,以后还要再做过 以后再也不用指针了!太恶心了!空指针可不止直接特判那么简单啊,竟然还要因为空指针写奇怪的分类 ...

  3. 洛谷P3273 [SCOI2011]棘手的操作

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

  4. 洛谷P4331 [BOI2004] Sequence 数字序列 [左偏树]

    题目传送门 数字序列 题目描述 给定一个整数序列 a1​,a2​,⋅⋅⋅,an​ ,求出一个递增序列 b1​<b2​<⋅⋅⋅<bn​ ,使得序列 ai​ 和 bi​ 的各项之差的绝对 ...

  5. 模板 可并堆【洛谷P3377】 【模板】左偏树(可并堆)

    P3377 [模板]左偏树(可并堆) 如题,一开始有N个小根堆,每个堆包含且仅包含一个数.接下来需要支持两种操作: 操作1: 1 x y 将第x个数和第y个数所在的小根堆合并(若第x或第y个数已经被删 ...

  6. 洛谷P3066 [USACO12DEC] 逃跑的Barn [左偏树]

    题目传送门 逃跑的Barn 题目描述 It's milking time at Farmer John's farm, but the cows have all run away! Farmer J ...

  7. 洛谷$P4331\ [BOI2004]\ Sequence$ 数字序列 左偏树

    正解:左偏树 解题报告: 传送门$QwQ$ 开始看到的时候$jio$得长得很像之前做的一个$dp$,,, 但是$dp$那题是说不严格这里是严格? 不难想到我们可以让$a_{i},b_{i}$同时减去$ ...

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

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

  9. 2333: [SCOI2011]棘手的操作[离线线段树]

    2333: [SCOI2011]棘手的操作 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2325  Solved: 909[Submit][Stat ...

随机推荐

  1. VS Code 配置 C/C++ 环境

    写作原因 微软的 VSCode 一直以来为人诟病的一个问题就是对于 C/C++ 工程的编译以及调试支持度有限,配置起来比较复杂,但是 vscode-cpptools 团队经过一段时间的 bug 修复之 ...

  2. each()和eq()

    今天工作的时候要遍历一个表格,于是我就想到了each(),也没看文档就开始写,大概是这么写的 $(".class").each(function(){ this.click(fun ...

  3. 针对移动设备的CSS3布局

    针对移动设备的CSS3布局 一些专业人士预测五年内移动设备将击败普通电脑成为网页浏览领域的霸主,不管这个预言是否应验,让网页在移动设备上较好的显示已经成为网页设计师和开发者的重要任务,本教程学习用CS ...

  4. 12款jQuery幻灯片插件和幻灯片特效教程

    jQuery 使用简单灵活,同时还有许多成熟的插件可供选择,它可以帮助你在项目中加入一些非常好的效果.滑块和幻灯片效果是常用的内容展示方式之一,这是一种在有限的网页空间内展示系列项目时非常好的方法.今 ...

  5. 【CodeForces】914 E. Palindromes in a Tree 点分治

    [题目]E. Palindromes in a Tree [题意]给定一棵树,每个点都有一个a~t的字符,一条路径回文定义为路径上的字符存在一个排列构成回文串,求经过每个点的回文路径数.n<=2 ...

  6. HDU 1394 Minimum Inversion Number (树状数组)

    题目链接 Problem Description The inversion number of a given number sequence a1, a2, ..., an is the numb ...

  7. 微信小程序迁移到头条小程序工具

    最近公司需要将微信小程序迁移到头条小程序,比较得知微信和头条小程序的写法类似,只有文件名称不同,相关的指令不同,以及头条在ttml绑定的数据不可使用function,于是就写了node脚本来实现这些重 ...

  8. 【文件上传】jquery之ajaxfileupload异步上传插件

    来自:http://www.blogjava.net/sxyx2008/archive/2010/11/02/336826.html 由于项目需求,在处理文件上传时需要使用到文件的异步上传.这里使用J ...

  9. Verilog笔记.5.同步、异步

    在数字电路中经常有同步synchronism.异步asynchronism的概念.异步指输入信号和时钟无关:同步指输入信号和时钟信号有关,实际上就是输入信号和时钟信号进行了与运算或者与非运算.实际开发 ...

  10. 设计模式之Composite

    设计模式总共有23种模式这仅仅是为了一个目的:解耦+解耦+解耦...(高内聚低耦合满足开闭原则) Composite定义? 将对象以树形结构组织起来,以达成“部分-整体” 的层次结构. 想到Compo ...