题目: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 二逼平衡树——线段树套平衡树的更多相关文章

  1. BZOJ3196二逼平衡树——线段树套平衡树(treap)

    此为平衡树系列最后一道:二逼平衡树您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询 ...

  2. [bzoj3196]Tyvj 1730 二逼平衡树——线段树套平衡树

    题目 Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名为k的值 3.修改某一位值上的数值 4.查 ...

  3. bzoj 3196二逼平衡树 线段树套平衡树

    比较裸的树套树,对于区间K值bz上有一道裸题,详见题解http://www.cnblogs.com/BLADEVIL/p/3455336.html(其实题解也不是很详细) //By BLADEVIL ...

  4. P3380 【模板】二逼平衡树(树套树)(线段树套平衡树)

    P3380 [模板]二逼平衡树(树套树) 前置芝士 P3369 [模板]普通平衡树 线段树套平衡树 这里写的是线段树+splay(不吸氧竟然卡过了) 对线段树的每个节点都维护一颗平衡树 每次把给定区间 ...

  5. 【BZOJ-3196】二逼平衡树 线段树 + Splay (线段树套平衡树)

    3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2271  Solved: 935[Submit][Stat ...

  6. BZOJ3196 二逼平衡树 【线段树套平衡树】

    题目 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名为k的值 3.修改某一位值上的数值 4.查询k在区间内的前驱(前驱 ...

  7. bzoj 3196/ Tyvj 1730 二逼平衡树 (线段树套平衡树)

    3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description ...

  8. P3380 【模板】二逼平衡树(树套树) 线段树套平衡树

    \(\color{#0066ff}{ 题目描述 }\) 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 查询k在区间内的排名 查询区间内排名为k的值 修改某一位值上 ...

  9. 树套树Day1线段树套平衡树bzoj3196

    您需要写一种数据结构,来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)5.查 ...

随机推荐

  1. Nginx的初识

    今日刚接触了解到Nginx的反向代理,正向代理,并发,集群,同个站点不同域名的解析访问等等. 1.反向代理:Nginx充当一个桥接的作用,对用户和服务端进行链接,进行服务端的代理,这样有什么好处: a ...

  2. 测试第一个Oracle存储过程

    存储过程语句 //简单存储过程的例子 //每调用一次打印一次hello world create or replace procedure sayhelloworld as begin dbms_ou ...

  3. Python基础之列表、元组、字典、集合的使用

    一.列表 1.列表定义 names=["Jhon","Lucy","Michel","Tom","Wiliam ...

  4. redis & macOS & python

    redis & macOS & python how to install python 3 on mac os x? https://docs.python.org/3/using/ ...

  5. [luoguP1098] 字符串的展开(模拟)

    传送门 一个模拟. 代码 #include <cstdio> #include <cstring> #include <iostream> #define iswo ...

  6. 【springmvc】传值的几种方式&&postman接口测试

    最近在用postman测试postman接口,对于springmvc传值这一块,测试了几种常用方式,总结一下.对于postman这个工具的使用也增加了了解.postman测试很棒,有了工具,测试接口, ...

  7. Object-C 打开工程,选择模拟起时,提示"no scheme"

    错误提示,如下图: 解决思路:

  8. mac idea快捷键(部分常用)

    shift+F6重命名 shift+enter 换到下一行 shift+F8等同eclipse的f8跳到下一个断点,也等同eclipse的F7跳出函数 F8等同eclipse的f6跳到下一步F7等同e ...

  9. Eclipse-Java代码规范和质量检查插件-SonarLint

    SonarQube(Sonar)之前的提供的本地工具是需要依赖SonarQube服务器的,这样导致其运行速度缓慢. 新出的SonarLint的扫描引擎直接安装在本地,速度超快,实时探测代码技术债务,给 ...

  10. Memcached与Spring集成的方式(待实践)

    主要是基于这几种方式http://www.cnblogs.com/EasonJim/p/7624822.html去实现与Spring集成,而个人建议使用Xmemcached去集成好一些,因为现在官方还 ...