【BZOJ2333】棘手的操作(左偏树,STL)

题面

BZOJ上看把。。。

题解

正如这题的题号

我只能\(2333\)

神TM棘手的题目。。。

前面的单点/联通块操作

很显然是一个左偏树+标记

(确实很显然,只是写死人。。。)

然后对于全局的最大值而言

搞一个\(multi\)来水

看起来真的简单。。

写起来真的想死。。。

记住:要特判一下已经联通的块就不要再去\(Merge\)了

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define MAX 300010
inline int read()
{
int x=0,t=1;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
int n;
multiset<int> S;
struct Node
{
int ls,rs,ff;
int v,dis;
int lz;
}t[MAX];
int Lazy,root;
int getf(int x){while(t[x].ff)x=t[x].ff;return x;}
void putlazy(int x,int w)
{
t[x].v+=w;
t[x].lz+=w;
}
void pushdown(int x)
{
if(!t[x].lz)return;
if(t[x].ls)putlazy(t[x].ls,t[x].lz);
if(t[x].rs)putlazy(t[x].rs,t[x].lz);
t[x].lz=0;
}
int Merge(int r1,int r2)
{
if(!r1||!r2)return r1+r2;
pushdown(r1);pushdown(r2);
if(t[r1].v<t[r2].v)swap(r1,r2);
t[r1].rs=Merge(t[r1].rs,r2);
t[t[r1].rs].ff=r1;
if(t[t[r1].ls].dis<t[t[r1].rs].dis)swap(t[r1].ls,t[r1].rs);
t[r1].dis=t[t[r1].rs].dis+1;
return r1;
}
void Update(int x)
{
if(!x)return;
if(t[t[x].ls].dis<t[t[x].rs].dis)swap(t[x].ls,t[x].rs);
t[x].dis=t[t[x].rs].dis+1;
Update(t[x].ff);
}
void Alldown(int x)
{
if(t[x].ff)Alldown(t[x].ff);
pushdown(x);
}
void Del(int x)
{
Alldown(x);
t[t[x].ls].ff=t[t[x].rs].ff=0;
if(t[t[x].ff].rs==x)t[t[x].ff].rs=0;
else t[t[x].ff].ls=0;
int rtt=getf(t[x].ff);
Merge(rtt,Merge(t[x].ls,t[x].rs));
Update(t[x].ff);
t[x].ff=t[x].ls=t[x].rs=0;
}
void Plus(int x,int w)//单点修改
{
int rtt=getf(x);
if(!t[x].ff)
{
S.erase(S.find(t[x].v));
t[t[x].ls].ff=t[t[x].rs].ff=0;
pushdown(x),rtt=Merge(t[x].ls,t[x].rs);
t[x].ff=t[x].ls=t[x].rs=0;
}
else Del(x),S.erase(S.find(t[rtt].v));
t[x].v+=w;
int gg=Merge(x,rtt);
S.insert(t[gg].v);
}
void AllPlus(int x,int w)
{
x=getf(x);
S.erase(S.find(t[x].v));
putlazy(x,w);
S.insert(t[x].v);
}
int main()
{
n=read();
for(int i=1;i<=n;++i)t[i].v=read(),S.insert(t[i].v);
int Q=read();
char ch[5];
while(Q--)
{
scanf("%s",ch);
if(ch[0]=='A')
{
if(ch[1]=='1')
{
int x=read(),v=read();
Plus(x,v);
}
else if(ch[1]=='2')
{
int x=read(),v=read();
AllPlus(x,v);
}
else Lazy+=read();
}
else if(ch[0]=='F')
{
if(ch[1]=='1')
{
int x=read();
Alldown(x);
printf("%d\n",t[x].v+Lazy);
}
else if(ch[1]=='2')
{
int x=read();
x=getf(x);
printf("%d\n",t[x].v+Lazy);
}
else printf("%d\n",*--S.end()+Lazy);
}
else
{
int x=read(),y=read();
x=getf(x),y=getf(y);
if(x==y)continue;
int kk=Merge(x,y);
S.erase(S.find(kk==x?t[y].v:t[x].v));
}
}
return 0;
}

【BZOJ2333】棘手的操作(左偏树,STL)的更多相关文章

  1. 洛谷P3273 [SCOI2011] 棘手的操作 [左偏树]

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

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

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

  3. 左偏树 / 非旋转treap学习笔记

    背景 非旋转treap真的好久没有用过了... 左偏树由于之前学的时候没有写学习笔记, 学得也并不牢固. 所以打算写这么一篇学习笔记, 讲讲左偏树和非旋转treap. 左偏树 定义 左偏树(Lefti ...

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

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

  5. 【BZOJ 2333 】[SCOI2011]棘手的操作(离线+线段树|可并堆-左偏树)

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

  6. P3378 【模板】堆 (内含左偏树实现)

    P3378 [模板]堆 题解 其实就是一个小根堆啦,STL就可以解决,但是拥有闲情雅致的我学习了Jelly_Goat的左偏树,增加了代码长度,妙啊 Solution 1 STL STL 里面prior ...

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

    作者:zifeiy 标签:左偏树 这篇随笔需要你在之前掌握 堆 和 二叉树 的相关知识点. 堆支持在 \(O(\log n)\) 的时间内进行插入元素.查询最值和删除最值的操作.在这里,如果最值是最小 ...

  8. 【bzoj2809】[Apio2012]dispatching 左偏树

    2016-05-31  15:56:57 题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2809 直观的思想是当领导力确定时,尽量选择薪水少的- ...

  9. 左偏树(Leftist Heap/Tree)简介及代码

    左偏树是一种常用的优先队列(堆)结构.与二叉堆相比,左偏树可以高效的实现两个堆的合并操作. 左偏树实现方便,编程复杂度低,而且有着不俗的效率表现. 它的一个常见应用就是与并查集结合使用.利用并查集确定 ...

随机推荐

  1. linux使用i/o内存访问外设

    一.linux中访问外设的方法. 1.IO端口(IO port) linux系统给外设分配不同的端口号,linux利用端口号来访问设备(驱动) (cpu x86) cpu访问外设通过端号,访问通过地址 ...

  2. 在linux内核中实现自己的系统调用

    如实现一个简单的打印:printk 1.cd linux-ok6410/kernel/ vim printk.cvoid sys_pk(){printk("<0>this is ...

  3. javascript 数字字母组合的随机数

    Math.random()方法用于生成,结果为0-1间的一个伪随机数(包括0,不包括1) ,通常的办法是结合parseInt().Math.floor() 或者 Math.ceil()进行四舍五入处理 ...

  4. 如何在Python中从零开始实现随机森林

    欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~ 决策树可能会受到高度变异的影响,使得结果对所使用的特定测试数据而言变得脆弱. 根据您的测试数据样本构建多个模型(称为套袋)可以减少这种差异,但是 ...

  5. MySQL开启binlog并且保存7天有效数据

    开启binlog日志(在[mysqld]下修改或添加如下配置): server-id=1 log-bin=mysql-bin binlog_format=MIXED binlog日志模式 Mysql复 ...

  6. go语言实现无限极分类

     // 应用分类二级菜单     AppCateNode struct {         Id int64 `json:"id"`         Name string `js ...

  7. 解决java.lang.IllegalArgumentException: No converter found for return value of type: class java.util.ArrayList这个问题

    今天使用SSM框架,用@ResponseBody注解,出现了这个问题 java.lang.IllegalArgumentException: No converter found for return ...

  8. thinkphp5判断移动或pc端访问并调用不同模板

    废话不多说,直接上代码 先修改\thinkphp\library\think\view\driver\Think.php文件 把 public function __construct($config ...

  9. mongodb的TTL索引介绍(超时索引)

    TTL索引是mongodb新支持的用于延时自动删除记录的一种索引.它仅包含一个字段,该字段值需要是Date()类型,并且不支持复合索引.可以指定某条记录在延时固定时间后自动删除.数据自动超时删除主要用 ...

  10. 在Ubuntu上安装PHPStudy组件

    phpStudy for Linux (lnmp+lamp一键安装包) phpStudy Linux版&Win版同步上线 支持Apache/Nginx/Tengine/Lighttpd/IIS ...