bzoj3196 二逼平衡树——线段树套平衡树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3196
人生中第一棵树套树!
写了一个晚上,成功卡时 9000ms+ 过了!
很要注意数组的大小,因为是树*树的大小嘛!
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int const maxn=2e6+,nn=5e4+,inf=1e9;//2e6!!
int n,m,tot,siz[maxn],c[maxn][],fa[maxn],key[maxn],mn,mx,a[nn];
struct N{
int l,r,rt;
}t[nn<<];
void update(int x){siz[x]=siz[c[x][]]+siz[c[x][]]+;}
void rotate(int x)
{
int y=fa[x],z=fa[y],d=(c[y][]==x);
if(z!=)c[z][c[z][]==y]=x;
fa[x]=z; fa[y]=x; fa[c[x][d^]]=y;
c[y][d]=c[x][d^]; c[x][d^]=y;
update(y); update(x);
}
void splay(int x,int f)//fa[x]=f
{
while(fa[x]!=f)
{
int y=fa[x],z=fa[y];
if(z!=f)// z 而非 y
{
if((c[y][]==x)^(c[z][]==y)) rotate(x);
else rotate(y);
}
rotate(x);
}
}
int find_pre(int x,int v)
{
if(!x)return ;
if(key[x]>=v) return find_pre(c[x][],v);
else
{
int y=find_pre(c[x][],v);
if(y)return y; else return x;
}
}
int find_k(int x,int k)
{
// if(!x)return 0;
if(siz[c[x][]]==k-)return x;
if(siz[c[x][]]>k-)return find_k(c[x][],k);
return find_k(c[x][],k-siz[c[x][]]-);
}
int find_suc(int x,int k)//后继
{
if(!x)return ;
if(key[x]<=k)return find_suc(c[x][],k);
else
{
int y=find_suc(c[x][],k);
if(y)return y; else return x;//说不定就是 x
}
}
int find_Suc(int x,int k)//相等中最小的
{
if(!x)return ;
if(key[x]<k)return find_Suc(c[x][],k);
else
{
int y=find_Suc(c[x][],k);
if(y)return y; else return x;//说不定就是 x
}
}
int query_k(int &x,int k)//查询 k 的排名
{
int p=find_Suc(x,k); splay(p,);//相等中最小的
x=p;
return siz[c[p][]]-;// -inf
}
int query(int &x,int k)//二分用
{
int p=find_suc(x,k); splay(p,);
x=p;
return siz[c[p][]]-;// -inf
}
void insert(int &x,int v)
{
int p=find_pre(x,v); splay(p,);
int y=find_k(c[p][],); splay(y,p);//p
tot++; siz[tot]=; fa[tot]=y; key[tot]=v; c[y][]=tot;
update(y); update(p);
x=p;//rt
}
void del(int &x,int v)
{
int p=find_pre(x,v); splay(p,);
int y=find_k(c[p][],); splay(y,p);//p
fa[c[y][]]=; c[y][]=;
update(y); update(p);
x=p;
}
void build(int x,int l,int r)
{
t[x].l=l; t[x].r=r;
t[x].rt=++tot; siz[tot]=; fa[tot]=; c[tot][]=tot+; key[tot]=-inf;
tot++; siz[tot]=; fa[tot]=tot-; key[tot]=inf;
for(int i=l;i<=r;i++)insert(t[x].rt,a[i]);
if(l==r)return;
int mid=(l+r)>>;
build(x<<,l,mid); build(x<<|,mid+,r);
}
int query_k(int x,int l,int r,int k)//查询 k 的排名
{
if(t[x].l>=l && t[x].r<=r)return query_k(t[x].rt,k);//<=k 的个数
int mid=(t[x].l+t[x].r)>>,ret=;//不是 l,r
if(mid>=l)ret+=query_k(x<<,l,r,k);//l,r,无需 l,mid ,因为自带 t[x].l,t[x].r
if(mid<r)ret+=query_k(x<<|,l,r,k);
return ret;
}
int query(int x,int l,int r,int k)//二分用 //<=mid的个数
{
if(t[x].l>=l && t[x].r<=r)return query(t[x].rt,k);
int mid=(t[x].l+t[x].r)>>,ret=;//不是 l,r
if(mid>=l)ret+=query(x<<,l,r,k);
if(mid<r)ret+=query(x<<|,l,r,k);
return ret;
}
void modify(int x,int p,int k)
{
insert(t[x].rt,k); del(t[x].rt,a[p]);
if(t[x].l==t[x].r)return;//
int mid=(t[x].l+t[x].r)>>;
if(p<=mid)modify(x<<,p,k);
else modify(x<<|,p,k);
}
int query_pre(int x,int l,int r,int k)
{
if(t[x].l>=l && t[x].r<=r)return key[find_pre(t[x].rt,k)];//返回 key ,因为需要比较
int mid=(t[x].l+t[x].r)>>,ret=;
if(mid>=l)ret=max(ret,query_pre(x<<,l,r,k));
if(mid<r)ret=max(ret,query_pre(x<<|,l,r,k));
return ret;
}
int query_suc(int x,int l,int r,int k)
{
if(t[x].l>=l && t[x].r<=r)return key[find_suc(t[x].rt,k)];//返回 key ,因为需要比较
int mid=(t[x].l+t[x].r)>>,ret=inf;
if(mid>=l)ret=min(ret,query_suc(x<<,l,r,k));
if(mid<r)ret=min(ret,query_suc(x<<|,l,r,k));
return ret;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
{
scanf("%d",&a[i]);
mn=min(mn,a[i]); mx=max(mx,a[i]);
}
build(,,n);
for(int i=,op,l,r,k;i<=m;i++)
{
scanf("%d",&op);
if(op!=)scanf("%d%d%d",&l,&r,&k);
if(op==)printf("%d\n",query_k(,l,r,k)+);//+1
if(op==)
{
int L=mn,R=mx,ans=;
while(L<=R)
{
int mid=(L+R)>>;
if(query(,l,r,mid)>=k)ans=mid,R=mid-;// >也可,因为查询的是 <=mid 的个数
else L=mid+;
}
printf("%d\n",ans);
}
if(op==)
{
int pos; scanf("%d%d",&pos,&k);
modify(,pos,k);
a[pos]=k;//!!!
}
if(op==)printf("%d\n",query_pre(,l,r,k));
if(op==)printf("%d\n",query_suc(,l,r,k));
}
return ;
}
bzoj3196 二逼平衡树——线段树套平衡树的更多相关文章
- BZOJ3196二逼平衡树——线段树套平衡树(treap)
此为平衡树系列最后一道:二逼平衡树您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询 ...
- [bzoj3196]Tyvj 1730 二逼平衡树——线段树套平衡树
题目 Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名为k的值 3.修改某一位值上的数值 4.查 ...
- bzoj 3196二逼平衡树 线段树套平衡树
比较裸的树套树,对于区间K值bz上有一道裸题,详见题解http://www.cnblogs.com/BLADEVIL/p/3455336.html(其实题解也不是很详细) //By BLADEVIL ...
- P3380 【模板】二逼平衡树(树套树)(线段树套平衡树)
P3380 [模板]二逼平衡树(树套树) 前置芝士 P3369 [模板]普通平衡树 线段树套平衡树 这里写的是线段树+splay(不吸氧竟然卡过了) 对线段树的每个节点都维护一颗平衡树 每次把给定区间 ...
- 【BZOJ-3196】二逼平衡树 线段树 + Splay (线段树套平衡树)
3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2271 Solved: 935[Submit][Stat ...
- BZOJ3196 二逼平衡树 【线段树套平衡树】
题目 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名为k的值 3.修改某一位值上的数值 4.查询k在区间内的前驱(前驱 ...
- bzoj 3196/ Tyvj 1730 二逼平衡树 (线段树套平衡树)
3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec Memory Limit: 128 MB[Submit][Status][Discuss] Description ...
- P3380 【模板】二逼平衡树(树套树) 线段树套平衡树
\(\color{#0066ff}{ 题目描述 }\) 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 查询k在区间内的排名 查询区间内排名为k的值 修改某一位值上 ...
- 树套树Day1线段树套平衡树bzoj3196
您需要写一种数据结构,来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)5.查 ...
随机推荐
- 第十七节:Scrapy爬虫框架之item.py文件以及spider中使用item
Scrapy原理图: item位于原理图的最左边 item.py文件是报存爬取数据的容器,他使用的方法和字典很相似,但是相比字典item多了额外的保护机制,可以避免拼写错误或者定义错误. 1.创建it ...
- 83-MACD 移动平均汇总/分离指标.(2015.7.3)
MACD 移动平均汇总/分离指标 ~计算: · EMA(12,t)=EMA(12,t-1) * 11/13 + Close * 2/13 · EMA(26,t)=EMA(26,t-1) * 25/27 ...
- jquery源码——noConflict实现
实现方式很简单:在初始化的时候,记录当前全局中jQuery和$两个变量的的值,用_jQuery和_$分别存放,调用noConflict方法时,使用_jQuery和_$分别恢复对应的值,并且返回jQue ...
- sqlite3 新建数据库的过程
有些东西,很简单,不过有坑,就变复杂了.我先说最简单的方法,新建一个空的txt文档,然后把后缀改为db就可以了.-_-蛋疼,其实一开始我是不知道的,也是后来成功新建db后发现db为0kb才大胆地做了这 ...
- HDU 1564 找规律博弈
题目大意是: 从n*n的方格角落的一个起点出发,每次移到上下左右一个未曾到达过的位置,谁不能走了谁就输了 想了好久都想不出,看了大神的题解 Orz了 果然博弈不是脑残的游戏啊... 这里从起点出发,将 ...
- CSU1217
就跟数字出现奇数次道理是一样的,将一个数转化为2进制后找出现奇数次个1的位置,最后将其输出来便是出现奇数次的数 #include <cstdio> int main() { int n,a ...
- 常见问题:Linux安装Python3步骤、Windows无法利用pip
Linux安装python3.6和第三方库的步骤: 我的Linux是CentOS 6.5版本 Linux下大部分系统默认自带python2.x的版本,最常见的是python2.6或python2.7, ...
- 原 linux添加虚拟ip(手动vip和keepalived方式)
https://blog.csdn.net/dear_snowing/article/details/68066544 https://www.cnblogs.com/liuyisai/p/59906 ...
- [bzoj1112][POI2008]砖块Klo_非旋转Treap
砖块Klo bzoj-1112 POI-2008 题目大意:$N$柱砖,希望有连续$K$柱的高度是一样的. 你可以选择以下两个动作 1:从某柱砖的顶端拿一块砖出来,丢掉不要了. 2:从仓库中拿出一块砖 ...
- crontab not running
there are mutliple ways to describle this issue 1. crontab not running 2. crontab not running and no ...