题目: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. CSS——可视化格式模型

    CSS的可视化格式模型 CSS中规定每一个元素都有自己的盒子模型(相当一规定了这个元素如何显示): 然后可视化格式模型则是把这些盒子模型按照规则摆放到页面上,也就是如何布局: 换句话说,盒子模型规定了 ...

  2. python flask获取微信用户信息报404,nginx问题

    在学习flask与微信公众号时问题,发现测试自动回复/wechat8008时正常,而测试获取微信用户信息/wechat8008/index时出现404.查询资料后收发是nginx配置问题. 在loca ...

  3. ABC077翻车实况

    今天强行打一波ABC,想作为信心赛,然而= = T1  日常练习读入&输出 T2  $STL$大法好,$sqrt$保平安,我强行递推$WA$了一圈,然后罚时++ T3  woc好难啊,$n=1 ...

  4. [luoguP1058] 立体图(超级大模拟(¬︿̫̿¬☆))

    传送门 看到题后整个人成了mengbier 但是仔细分析一下就很简单了,先确定好输出的图的长和宽. 然后从输入的矩形的左上角的最下面的开始填充,顺序是从下到上,从左到右,从后往前. 填充的时候直接覆盖 ...

  5. 守卫者的挑战(codevs 1997)

    题目描述 Description 打开了黑魔法师Vani的大门,队员们在迷宫般的路上漫无目的地搜寻着关押applepi的监狱的所在地.突然,眼前一道亮光闪过.“我,Nizem,是黑魔法圣殿的守卫者.如 ...

  6. 和式 sigma的使用

    1.和式 0)艾佛森约定 艾佛森约定可以用来简化和式,艾佛森约定中的\([p(k)]\)就是一个限制条件,类似于一个\(bool\)函数,我们可以这样写 \[ \sum_{1<k<n}a_ ...

  7. HDU - 2059 龟兔赛跑(多阶段决策dp)

    http://acm.hdu.edu.cn/showproblem.php?pid=2059 初始把起点和终点也算做充电站,设dp[i]是到第i个充电站的最短时间,那么dp[n+1]即是乌龟到达终点的 ...

  8. hdu - 1104 Remainder (bfs + 数论)

    http://acm.hdu.edu.cn/showproblem.php?pid=1104 注意这里定义的取模运算和计算机的%是不一样的,这里的取模只会得到非负数. 而%可以得到正数和负数. 所以需 ...

  9. Java 添加、更新和移除PDF超链接

    简介 PDF超链接用一个简单的链接包含了大量的信息,满足了人们在不占用太多空间的情况下渲染外部信息的需求.下面将介绍通过Java 在PDF中添加.更新和移除超链接. (一)工具使用: Free Spi ...

  10. hibernate dynamic-update="true"属性不起作用原因(转载)

    原文地址: https://yan-sa.iteye.com/blog/1913684 由于我在action层使用了注解多例@Scope("prototype"),而在dao层默认 ...