题目: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. 集训第五周动态规划 D题 LCS

    Description In a few months the European Currency Union will become a reality. However, to join the ...

  2. 【Codeforces 492D】Vanya and Computer Game

    [链接] 我是链接,点我呀:) [题意] 题意 [题解] 第一个人攻击一次需要1/x秒 第二个人攻击一次需要1/y秒 这两个数字显然都是小数. 我们可以二分最后用了多少时间来攻击. 显然这个是有单调性 ...

  3. python之更加抽象 2014-4-6

    #更加抽象 12:50pm- 14:50 p112- 1.对象的魔力 多态 如count 在多种数据类型中都可以实现计数的功能 封装 对全局作用域中其他区域隐藏多余信息的原则 继承2.类和类型 创建类 ...

  4. JQuery_九大选择器

    JQuery_九大选择器-----https://blog.csdn.net/pseudonym_/article/details/76093261

  5. 如何使用JDK1.6 API

    如何使用JDK1.6 API-------https://jingyan.baidu.com/article/54b6b9c0e39a102d583b47d5.html  

  6. 看板娘 & 二次元 & live2d

    live2d https://l2dwidget.js.org/dev.html https://github.com/xiazeyu/live2d-widget.js 看板娘 要切换看板娘吗? ht ...

  7. UVA 10652 凸包问题

    #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> # ...

  8. 前端开发:HTML

    静态页面: 没有与用户进行交互,而仅仅是用户浏览的一个网页 动态网页:就是用户不仅仅可以浏览网页,还可以与服务器交互 Web前端应用场景:公司官网(在PC通过浏览器访问公司网站).移动端网页(在手机上 ...

  9. 【NOIP2016】天天爱跑步(树上差分)

    题意: 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.?天天爱跑步?是一个养成类游戏,需要 玩家每天按时上线,完成打卡任务.这个游戏的地图可以看作一一棵包含 N个结点 ...

  10. 【BZOJ2527】Meteors(整体二分)

    题意: Byteotian Interstellar Union有N个成员国.现在它发现了一颗新的星球,这颗星球的轨道被分为M份(第M份和第1份相邻),第i份上有第Ai个国家的太空站. 这个星球经常会 ...