刷题总结——单旋(HNOI2017 bzoj4825)
题目:
Description
Input
Output
Sample Input
1 2
1 1
1 3
4
5
Sample Output
2
2
2
2
题解:
首先是插入操作。容易发现,节点的深度是当前spaly中比它小中最大的、比它大的中最小的,两个节点深度更大值+1。
接下来是旋转&删除。旋转最小、大值的思路类似,这里只讨论最小值。画图可以发现当前最小值右子树的深度不变,自己深度变为1,其余点深度+1。
把根删除,就是其它节点深度全部-1.
那么现在就要支持以下操作:在序列中间插入一个数、区间加减、单点修改、单点查询、以及寻找第一个(或最后一个)比某值小的数。这题没有强制在线,可以用线段树解决。如果在线可以打splay
时间复杂度O(nlogn)
至于如何维护就很麻烦了···线段树的左右区间为离散化后的键值,用tr,mx,mi分别表示键值区间内深度最小值,键值区间内键值最大的点的深度··键值区间内键值最小的点的深度,前一个用于求每个点的再spaly中的father,后两个用于求前驱后继··(具体见代码)
md好难打啊艹
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<cctype>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const int N=;
int tr[N*],mx[N*],mi[N*],tag[N*],cnt[N*],b[N],now,a[N],tot,m,n,op[N],deep;
inline int R()
{
char c;int f=;
for(c=getchar();c<''||c>'';c=getchar());
for(;c<=''&&c>='';c=getchar())
f=(f<<)+(f<<)+c-'';
return f;
}
inline void lsh()
{
sort(b+,b+n+);
for(int i=;i<=n;i++)
a[i]=lower_bound(b+,b+n+,a[i])-b;
}
inline void update(int k)
{
if(cnt[k*]) mi[k]=mi[k*];else mi[k]=mi[k*+];
if(cnt[k*+]) mx[k]=mx[k*+];else mx[k]=mx[k*];
tr[k]=min(tr[k*],tr[k*+]);cnt[k]=cnt[k*]+cnt[k*+];
}
inline void pushdown(int k)
{
if(tag[k])
{
if(cnt[k*])
tag[k*]+=tag[k],mi[k*]+=tag[k],mx[k*]+=tag[k],tr[k*]+=tag[k];
if(cnt[k*+])
tag[k*+]+=tag[k],mi[k*+]+=tag[k],mx[k*+]+=tag[k],tr[k*+]+=tag[k];
tag[k]=;
}
}
inline int pre(int k,int l,int r,int v)
{
if(r==v)
return mx[k];
int mid=(l+r)/;
pushdown(k);
if(v<=mid) return pre(k*,l,mid,v);
int t=pre(k*+,mid+,r,v);
if(t) return t;
else return mx[k*];
}
inline int nxt(int k,int l,int r,int v)
{
if(l==v)
return mi[k];
int mid=(l+r)/;
pushdown(k);
if(v>mid) return nxt(k*+,mid+,r,v);
int t=nxt(k*,l,mid,v);
if(t) return t;
else return mi[k*+];
}
inline int getmin(int k,int l,int r)
{
if(l==r)
{
deep=tr[k];return l;
}
pushdown(k);
int mid=(l+r)/;
if(cnt[k*]) return getmin(k*,l,mid);
else return getmin(k*+,mid+,r);
}
inline int getmax(int k,int l,int r)
{
if(l==r)
{
deep=tr[k];return l;
}
pushdown(k);
int mid=(l+r)/;
if(cnt[k*+]) return getmax(k*+,mid+,r);
else return getmax(k*,l,mid);
}
inline void insert(int k,int l,int r,int dep,int v)
{
if(l==r)
{
tr[k]=mx[k]=mi[k]=dep;cnt[k]=;return;
}
pushdown(k);
int mid=(l+r)/;
if(v<=mid) insert(k*,l,mid,dep,v);
else insert(k*+,mid+,r,dep,v);
update(k);
}
inline void Delete(int k,int l,int r,int v)
{
if(l==r)
{
tr[k]=n,mx[k]=mi[k]=cnt[k]=;return;
}
pushdown(k);
int mid=(l+r)/;
if(v<=mid) Delete(k*,l,mid,v);
else Delete(k*+,mid+,r,v);
update(k);
}
inline int find1(int k,int l,int r,int dep)
{
if(l==r) return l;
pushdown(k);
int mid=(l+r)/;
if(cnt[k*]&&tr[k*]<dep) return find1(k*,l,mid,dep);
return find1(k*+,mid+,r,dep);
}
inline int find2(int k,int l,int r,int dep)
{
if(l==r) return l;
pushdown(k);
int mid=(l+r)/;
if(cnt[k*+]&&tr[k*+]<dep) return find2(k*+,mid+,r,dep);
return find2(k*,l,mid,dep);
}
inline void modify(int k,int l,int r,int x,int y,int v)
{
if(!cnt[k]) return;
if(l>=x&&r<=y)
{
tr[k]+=v,mx[k]+=v,mi[k]+=v,tag[k]+=v;
return;
}
pushdown(k);
int mid=(l+r)/;
if(x<=mid) modify(k*,l,mid,x,y,v);
if(y>mid) modify(k*+,mid+,r,x,y,v);
update(k);
}
int main()
{
//freopen("a.in","r",stdin);
m=R();
for(int i=;i<=m;i++)
{
op[i]=R();
if(op[i]==) a[++n]=R(),b[n]=a[n];
}
lsh();n++;memset(tr,0x3f3f3f3f,sizeof(tr));
for(int i=;i<=m;i++)
{
if(op[i]==)
{
now++;
insert(,,n,deep=max(pre(,,n,a[now]),nxt(,,n,a[now]))+,a[now]);
}
else if(op[i]==||op[i]==)
{
int q=getmin(,,n),p;
Delete(,,n,q);p=find1(,,n,deep);modify(,,n,p,n,);
if(op[i]==) insert(,,n,,q);else modify(,,n,,n,-);
}
else
{
int q=getmax(,,n),p;
Delete(,,n,q);p=find2(,,n,deep);modify(,,n,,p,);
if(op[i]==) insert(,,n,,q);else modify(,,n,,n,-);
}
printf("%d\n",deep);
}
return ;
}
刷题总结——单旋(HNOI2017 bzoj4825)的更多相关文章
- 【刷题】BZOJ 4825 [Hnoi2017]单旋
Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据结构,因为代码好写,功能多,效率高,掌握这种数据结构成为了 H 国的必 ...
- 【刷题】BZOJ 4830 [Hnoi2017]抛硬币
Description 小A和小B是一对好朋友,他们经常一起愉快的玩耍.最近小B沉迷于**师手游,天天刷本,根本无心搞学习.但是已经入坑了几个月,却一次都没有抽到SSR,让他非常怀疑人生.勤勉的小A为 ...
- 刷题总结——影魔(HNOI2017 BZOJ4826 线段树+扫描线)
题目: Description 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样 的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄 ...
- C#LeetCode刷题之#447-回旋镖的数量(Number of Boomerangs)
问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3792 访问. 给定平面上 n 对不同的点,"回旋镖&q ...
- 【刷题】BZOJ 4827 [Hnoi2017]礼物
Description 我的室友最近喜欢上了一个可爱的小女生.马上就要到她的生日了,他决定买一对情侣手 环,一个留给自己,一个送给她.每个手环上各有 n 个装饰物,并且每个装饰物都有一定的亮度.但是在 ...
- C#LeetCode刷题之#59-螺旋矩阵 II(Spiral Matrix II)
目录 问题 示例 分析 问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3678 访问. 给定一个正整数 n,生成一 ...
- C#LeetCode刷题之#54-螺旋矩阵(Spiral Matrix)
问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3672 访问. 给定一个包含 m x n 个元素的矩阵(m 行, ...
- C#LeetCode刷题-数组
数组篇 # 题名 刷题 通过率 难度 1 两数之和 C#LeetCode刷题之#1-两数之和(Two Sum) 43.1% 简单 4 两个排序数组的中位数 C#LeetCode刷题之#4-两个排序数组 ...
- C#LeetCode刷题-哈希表
哈希表篇 # 题名 刷题 通过率 难度 1 两数之和 C#LeetCode刷题之#1-两数之和(Two Sum) 42.8% 简单 3 无重复字符的最长子串 24.2% 中等 18 四数之和 ...
随机推荐
- Cenos7—安装
1. 进入安装界面 2. 选择语言 3. 进行分区 4. 设置root密码
- sql快速删除所用表,视图,存储过程
[http://www.th7.cn/db/mssql/2011-07-07/10127.shtml#userconsent#] 删除用户表 .select 'DROP TABLE '+name fr ...
- SQL学习总结笔记
SQL语句的效率不仅是sql语句的设计还有一些其他的原因比如网络 .是否有视图.是否有索引等等.这里主要描述的是我个人对于sql设计方面优化的一些见解: 首先要说明一下的是数据库SQL解析顺序: (1 ...
- c++ json字符串转换成map管理
在cocos2dx for lua中,我们经常通过lua的table传入c++使用,然后早c++层操作数据. 实现步骤大致如下: table->string->c++层->通过rap ...
- OC和C++的混用2
苹果的Objective-C编译器允许用户在同一个源文件里自由地混合使用C++和Objective-C,混编后的语言叫Objective-C++.有了它,你就可以在Objective-C应用程序中使用 ...
- Where art thou-freecodecamp算法题目
Where art thou 1.要求 写一个 function,它遍历一个对象数组(第一个参数)并返回一个包含相匹配的属性-值对(第二个参数)的所有对象的数组. 如果返回的数组中包含 source ...
- 数据结构实用C语言基础
大纲: 主要介绍了C语言中的指针,内存分配,两种传参方式,typedef的简单用法 关于C语言中的指针: 指针变量也称为指针(Pointer) 例如:int* p; 则p为一个指向int类型的指针. ...
- python中文件操作的基本方法
在python中对一个文件进行操作,分为三大步:打开,操作,关闭 首先创建一个文件hello,里面内容为hello world 一.打开一个文件 1.#open(‘文件名或文件路径’,‘操作模式’,文 ...
- 数据挖掘算法——Apriori
在上一篇数据挖掘入门算法整理中提到,Apriori算法是关联规则算法中使用最为广泛的算法,这次我们就来学习下该算法的基本知识. 一.算法概述 Apriori 算法是一种最有影响力的挖掘布尔关联规则的频 ...
- Java学习——面对对象的思想入门
本文是看过<head first Java>之后的一点感悟,写点东西帮忙以后回忆,Java目前在我的工作中用到还不多,而我又对面对对象的编程非常的感兴趣.曾经在MFC平台上写过 ...