【BZOJ2333】棘手的操作(左偏树,STL)
【BZOJ2333】棘手的操作(左偏树,STL)
题面
题解
正如这题的题号
我只能\(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)的更多相关文章
- 洛谷P3273 [SCOI2011] 棘手的操作 [左偏树]
题目传送门 棘手的操作 题目描述 有N个节点,标号从1到N,这N个节点一开始相互不连通.第i个节点的初始权值为a[i],接下来有如下一些操作: U x y: 加一条边,连接第x个节点和第y个节点 A1 ...
- 洛谷.3273.[SCOI2011]棘手的操作(左偏树)
题目链接 还是80分,不是很懂. /* 七个操作(用左偏树)(t2表示第二棵子树): 1.合并:直接合并(需要将一个t2中原有的根节点删掉) 2.单点加:把这个点从它的堆里删了,加了再插入回去(有负数 ...
- 左偏树 / 非旋转treap学习笔记
背景 非旋转treap真的好久没有用过了... 左偏树由于之前学的时候没有写学习笔记, 学得也并不牢固. 所以打算写这么一篇学习笔记, 讲讲左偏树和非旋转treap. 左偏树 定义 左偏树(Lefti ...
- BZOJ2333 [SCOI2011]棘手的操作 堆 左偏树 可并堆
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ2333 题意概括 有N个节点,标号从1到N,这N个节点一开始相互不连通.第i个节点的初始权值为a[i ...
- 【BZOJ 2333 】[SCOI2011]棘手的操作(离线+线段树|可并堆-左偏树)
2333: [SCOI2011]棘手的操作 Description 有N个节点,标号从1到N,这N个节点一开始相互不连通.第i个节点的初始权值为a[i],接下来有如下一些操作: U x y: 加一条边 ...
- P3378 【模板】堆 (内含左偏树实现)
P3378 [模板]堆 题解 其实就是一个小根堆啦,STL就可以解决,但是拥有闲情雅致的我学习了Jelly_Goat的左偏树,增加了代码长度,妙啊 Solution 1 STL STL 里面prior ...
- 洛谷P3377 【模板】左偏树(可并堆) 题解
作者:zifeiy 标签:左偏树 这篇随笔需要你在之前掌握 堆 和 二叉树 的相关知识点. 堆支持在 \(O(\log n)\) 的时间内进行插入元素.查询最值和删除最值的操作.在这里,如果最值是最小 ...
- 【bzoj2809】[Apio2012]dispatching 左偏树
2016-05-31 15:56:57 题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2809 直观的思想是当领导力确定时,尽量选择薪水少的- ...
- 左偏树(Leftist Heap/Tree)简介及代码
左偏树是一种常用的优先队列(堆)结构.与二叉堆相比,左偏树可以高效的实现两个堆的合并操作. 左偏树实现方便,编程复杂度低,而且有着不俗的效率表现. 它的一个常见应用就是与并查集结合使用.利用并查集确定 ...
随机推荐
- PHP的 first day of 和 last day of
话不多说,先上代码(当前是2017年6月2日) echo date("Y-m-d", strtotime("2017-02 first day of")).'& ...
- ss-redir 的 iptables 配置(透明代理)
透明代理指对客户端透明,客户端不需要进行任何设置就使用了网管设置的代理规则 创建 /etc/ss-redir.json 本地监听 7777 运行ss-redir -v -c /etc/ss-redir ...
- Pycharm常用的使用方法
PyCharm是一种Python IDE,带有一整套可以帮助用户在使用Python语言开发时提高其效率的工具,比如调试.语法高亮.Project管理.代码跳转.智能提示.自动完成.单元测试.版本控制. ...
- SDP(8):文本式数据库-MongoDB-Scala基本操作
MongoDB是一种文本式数据库.与传统的关系式数据库最大不同是MongoDB没有标准的格式要求,即没有schema,合适高效处理当今由互联网+商业产生的多元多态数据.MongoDB也是一种分布式数据 ...
- [翻译] 编写高性能 .NET 代码--第二章 GC -- 减少大对象堆的碎片,在某些情况下强制执行完整GC,按需压缩大对象堆,在GC前收到消息通知,使用弱引用缓存对象
减少大对象堆的碎片 如果不能完全避免大对象堆的分配,则要尽量避免碎片化. 对于LOH不小心就会有无限增长,但LOH使用的空闲列表机制可以减轻增长的影响.利用这个空闲列表,我们可以在两块分配区域中间找到 ...
- PHP函数register_shutdown_function的用法
register_shutdown_function这个函数是在PHP程序运行结束之前调用的,用这个函数可以做很多,比如调用运行发生致命错误中止的原因,或者调试程序的执行时间等. PHP终止的情况有哪 ...
- 生成1~n的排列
直接递归打印. 代码如下 #include<cstdio> void dfs(int *a,int cur,int n) { if(cur==n) { for(int i=0;i<n ...
- uva10976
数学题. 1. 因为 1/k = 1/x +1/y 所以 1/k > 1/y 那么 y > k 2 . 因为 x >= y 所以 1/k - 1/y <= 1/y 那么 y & ...
- uva1395 枚举不同区间的最小生成树
枚举起点,求最小生成树.如果当前不能实现n个点连通,直接不再枚举. AC代码: #include<cstdio> #include<algorithm> using names ...
- 算法训练 K好数 数位DP+同余定理
思路:d(i,j)表示以i开头,长度为j的K好数的个数,转移方程就是 for(int u = 0; u < k; ++u) { int x = abs(i - u); if(x == 1) co ...