题解:

替罪羊树

(讲道理昨天讲课我一点都听不懂)

alpha取到0.75比较好(当然啦可能其他的更好)

每当不满足条件的时候就重构

代码:

#include<bits/stdc++.h>
using namespace std;
const double alpha=0.75;
const int N=,M=;
int tmp,n,m,sz,lastans,root,v[M],dfn[M],rt[M],ls[M],rs[M];
struct seg{int l,r,sum;}a[N];
vector<int> rec,t,p;
inline int newnode()
{
if (!rec.size())return ++sz;
else
{
int k=rec.back();
rec.pop_back();
return k;
}
}
void reclaim(int &x)
{
if (!x)return;
rec.push_back(x);
reclaim(a[x].l);
reclaim(a[x].r);
a[x].sum=;x=;
}
void insert(int &k,int l,int r,int val,int f)
{
if (!k)k=newnode();
if (l==r)
{
a[k].sum+=f;
return;
}
int mid=(l+r)>>;
if (val<=mid)insert(a[k].l,l,mid,val,f);
else insert(a[k].r,mid+,r,val,f);
a[k].sum=a[a[k].l].sum+a[a[k].r].sum;
if (!a[k].sum)reclaim(k);
}
void build(int &k,int l,int r)
{
if (l>r)return;
if (l==r)
{
k=dfn[l];
insert(rt[k],,,v[k],);
return;
}
int mid=(l+r)>>;
k=dfn[mid];
build(ls[k],l,mid-);
build(rs[k],mid+,r);
for (int i=l;i<=r;i++)insert(rt[k],,,v[dfn[i]],);
}
void del(int &x)
{
if(!x)return;
reclaim(rt[x]);
del(ls[x]);
p.push_back(x);
del(rs[x]);
x=;
}
void rebuild(int &x)
{
del(x);
int s1=p.size();
for (int i=;i<=s1;i++)dfn[i]=p[i-];
build(x,,s1);
p.clear();
}
int modify(int k,int x,int val)
{
insert(rt[k],,,val,);
int t,L=a[rt[ls[k]]].sum;
if (L+==x){t=v[k];v[k]=val;}
else if (L>=x)t=modify(ls[k],x,val);
else t=modify(rs[k],x-L-,val);
insert(rt[k],,,t,-);
return t;
}
void query(int k,int l,int r)
{
int L=a[rt[ls[k]]].sum,R=a[rt[k]].sum;
if (l==&&r==R){t.push_back(rt[k]);return;}
if (l<=L+&&r>=L+)p.push_back(v[k]);
if (r<=L)query(ls[k],l,r);
else if (l>L+)query(rs[k],l-L-,r-L-);
else
{
if (l<=L)query(ls[k],l,L);
if (R>L+)query(rs[k],,r-L-);
}
}
int solve_query(int L,int R,int K)
{
query(root,L,R);
K--;
int l=,r=,s1=t.size(),s2=p.size();
while(l<r)
{
int mid=(l+r)>>,sum=;
for (int i=;i<s1;i++)sum+=a[a[t[i]].l].sum;
for (int i=;i<s2;i++)
if(p[i]>=l&&p[i]<=mid)sum++;
if (K<sum)
{
for (int i=;i<s1;i++)t[i]=a[t[i]].l;
r=mid;
}
else
{
for (int i=;i<s1;i++)t[i]=a[t[i]].r;
l=mid+;K-=sum;
}
}
t.clear();p.clear();
return l;
}
void insert(int &k,int x,int val)
{
if (!k)
{
k=++n;
insert(rt[k],,,val,);
v[k]=val;
return;
}
insert(rt[k],,,val,);
int L=a[rt[ls[k]]].sum;
if (L>=x)insert(ls[k],x,val);
else insert(rs[k],x-L-,val);
if (a[rt[k]].sum*alpha>max(a[rt[ls[k]]].sum,a[rt[rs[k]]].sum))
{
if (tmp)
{
if (ls[k]==tmp)rebuild(ls[k]);
else rebuild(rs[k]);
tmp=;
}
}
else tmp=k;
}
int main()
{
scanf("%d",&n);
for (int i=;i<=n;i++)scanf("%d",&v[i]);
for (int i=;i<=n;i++)dfn[i]=i;
build(root,,n);
scanf("%d",&m);
char s[];
int x,y,k;
while (m--)
{
scanf("%s",&s);
scanf("%d%d",&x,&y);
x^=lastans;y^=lastans;
if (s[]=='Q')
{
scanf("%d",&k);
k^=lastans;
lastans=solve_query(x,y,k);
printf("%d\n",lastans);
}
if (s[]=='M')modify(root,x,y);
if (s[]=='I')
{
tmp=;
insert(root,x-,y);
if (tmp)
{
tmp=;
rebuild(root);
}
}
}
}

bzoj3065的更多相关文章

  1. [BZOJ3065]带插入区间K小值 解题报告 替罪羊树+值域线段树

    刚了一天的题终于切掉了,数据结构题的代码真**难调,这是我做过的第一道树套树题,做完后感觉对树套树都有阴影了......下面写一下做题记录. Portal Gun:[BZOJ3065]带插入区间k小值 ...

  2. 【BZOJ3065】带插入区间K小值 替罪羊树+权值线段树

    [BZOJ3065]带插入区间K小值 Description 从前有n只跳蚤排成一行做早操,每只跳蚤都有自己的一个弹跳力a[i].跳蚤国王看着这些跳蚤国欣欣向荣的情景,感到非常高兴.这时跳蚤国王决定理 ...

  3. bzoj3065: 带插入区间K小值

    无聊来写了下 一开始发现树高是O(n)的,然后就MLE了,进去看了下发现没有重构! 看了半天发现调用错了函数 然后进去又发现不满足sz = ch[0]->sz + ch[1]->sz + ...

  4. BZOJ3065(替罪羊树套线段树)

    以前看到这题都瑟瑟发抖,终于过了心情舒畅. 按下标为关键字建替罪羊树,每个结点开一个权值线段树,维护的这个结点代表的子树的信息. 这题还得垃圾回收,自己yy的,不知对不对.. #include < ...

  5. 【bzoj3065】: 带插入区间K小值 详解——替罪羊套函数式线段树

    不得不说,做过最爽的树套树———— 由于有了区间操作,我们很容易把区间看成一棵平衡树,对他进行插入,那么外面一层就是平衡树了,这就与我们之前所见到的不同了.我们之前所见到的大多数是线段树套平衡树而此题 ...

  6. BZOJ3065 带插入区间K小值 || 洛谷P4278

    这是一道让我崩溃的题...... 然鹅洛谷上时限被改然后只有20分......好像所有人都被卡了(雾) 由于替罪羊树不是依靠旋转操作而是依靠暴力重构的方式维护树的平衡,所以我们可以考虑使用替罪羊树套区 ...

  7. 【函数式权值分块】【块状链表】bzoj3065 带插入区间K小值

    显然是块状链表的经典题.但是经典做法的复杂度是O(n*sqrt(n)*log^2(n))的,出题人明确说了会卡掉. 于是我们考虑每个块内记录前n个块的权值分块. 查询的时候差分什么的,复杂度就是O(n ...

  8. 「BZOJ3065」带插入区间第K小值 替罪羊树×线段树

    题目描述 从前有\(n\)只跳蚤排成一行做早操,每只跳蚤都有自己的一个弹跳力\(a_i\).跳蚤国王看着这些跳蚤国欣欣向荣的情景,感到非常高兴.这时跳蚤国王决定理性愉悦一下,查询区间\(k\)小值.他 ...

  9. [bzoj3065] 带插入区间第k小值 [重量平衡树套线段树]

    题面 传送门 思路 发现强制在线了...... 本来可以树套树解决的问题,现在外层不能使用线段树了,拿什么替代呢? 我们需要一种支持单点插入.下套数据结构.数据结构上传合并复杂度最多单log,不能旋转 ...

随机推荐

  1. TeeChart的坐标轴

    TeeChart一共有六个坐标轴,一下是默认值 tChart1.Axes.Bottom.Visible = true;//横轴 tChart1.Axes.Left.Visible = true;//纵 ...

  2. 第十一章 非对称加密算法--DH

    注意:本节内容主要参考自<Java加密与解密的艺术(第2版)>第8章“高等加密算法--非对称加密算法” 11.1.非对称加密算法 特点: 发送方和接收方均有一个密钥对(公钥+私钥),其中公 ...

  3. java中子类实例化过程中的内存分配

    知识点: 子类继承父类之后,实例化子类时,内存中子类是如何分配内存的呢? 下面,自己会结合一个例子,解释一下,一个子类实例化过程中,内存是如何分配的 参考博客:http://www.cnblogs.c ...

  4. shell 字符串运算符

    字符串运算符 下表列出了常用的字符串运算符,假定变量 a 为 "abc",变量 b 为 "efg": 运算符 说明 举例 = 检测两个字符串是否相等,相等返回 ...

  5. Python day17 模块介绍1(time,random)

    module模块和包的介绍(略掉了) 常用模块 # time模块 import time print(time.time())#时间戳,在1970年开始到现在一共多少秒 print(time.gmti ...

  6. Mask R-CNN论文理解

    摘要: Mask RCNN可以看做是一个通用实例分割架构. Mask RCNN以Faster RCNN原型,增加了一个分支用于分割任务. Mask RCNN比Faster RCNN速度慢一些,达到了5 ...

  7. Codeforces 912E - Prime Gift

    912E - Prime Gift 思路: 折半枚举+二分check 将素数分成两个集合(最好按奇偶位置来,保证两集合个数相近),这样每个集合枚举出来的小于1e18的积个数小于1e6. 然后二分答案, ...

  8. Python使用base64编码的问题

    有的时候,在base64解码的时候,由于字节问题出现解码错误.解决的办法就是不足原base64子串的长度: def decode_base64(data): """ De ...

  9. 如何给wpf的按钮添加背景图片

    1:简单实用 <Button Height="143" HorizontalAlignment="Left" Margin="30,34,0,0 ...

  10. php--------返回404状态

    php header()返回404状态代码的两种方式 //方式一 header('HTTP/1.1 404 Not Found');exit('404') //方式二 header("sta ...