bzoj3065
题解:
替罪羊树
(讲道理昨天讲课我一点都听不懂)
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的更多相关文章
- [BZOJ3065]带插入区间K小值 解题报告 替罪羊树+值域线段树
刚了一天的题终于切掉了,数据结构题的代码真**难调,这是我做过的第一道树套树题,做完后感觉对树套树都有阴影了......下面写一下做题记录. Portal Gun:[BZOJ3065]带插入区间k小值 ...
- 【BZOJ3065】带插入区间K小值 替罪羊树+权值线段树
[BZOJ3065]带插入区间K小值 Description 从前有n只跳蚤排成一行做早操,每只跳蚤都有自己的一个弹跳力a[i].跳蚤国王看着这些跳蚤国欣欣向荣的情景,感到非常高兴.这时跳蚤国王决定理 ...
- bzoj3065: 带插入区间K小值
无聊来写了下 一开始发现树高是O(n)的,然后就MLE了,进去看了下发现没有重构! 看了半天发现调用错了函数 然后进去又发现不满足sz = ch[0]->sz + ch[1]->sz + ...
- BZOJ3065(替罪羊树套线段树)
以前看到这题都瑟瑟发抖,终于过了心情舒畅. 按下标为关键字建替罪羊树,每个结点开一个权值线段树,维护的这个结点代表的子树的信息. 这题还得垃圾回收,自己yy的,不知对不对.. #include < ...
- 【bzoj3065】: 带插入区间K小值 详解——替罪羊套函数式线段树
不得不说,做过最爽的树套树———— 由于有了区间操作,我们很容易把区间看成一棵平衡树,对他进行插入,那么外面一层就是平衡树了,这就与我们之前所见到的不同了.我们之前所见到的大多数是线段树套平衡树而此题 ...
- BZOJ3065 带插入区间K小值 || 洛谷P4278
这是一道让我崩溃的题...... 然鹅洛谷上时限被改然后只有20分......好像所有人都被卡了(雾) 由于替罪羊树不是依靠旋转操作而是依靠暴力重构的方式维护树的平衡,所以我们可以考虑使用替罪羊树套区 ...
- 【函数式权值分块】【块状链表】bzoj3065 带插入区间K小值
显然是块状链表的经典题.但是经典做法的复杂度是O(n*sqrt(n)*log^2(n))的,出题人明确说了会卡掉. 于是我们考虑每个块内记录前n个块的权值分块. 查询的时候差分什么的,复杂度就是O(n ...
- 「BZOJ3065」带插入区间第K小值 替罪羊树×线段树
题目描述 从前有\(n\)只跳蚤排成一行做早操,每只跳蚤都有自己的一个弹跳力\(a_i\).跳蚤国王看着这些跳蚤国欣欣向荣的情景,感到非常高兴.这时跳蚤国王决定理性愉悦一下,查询区间\(k\)小值.他 ...
- [bzoj3065] 带插入区间第k小值 [重量平衡树套线段树]
题面 传送门 思路 发现强制在线了...... 本来可以树套树解决的问题,现在外层不能使用线段树了,拿什么替代呢? 我们需要一种支持单点插入.下套数据结构.数据结构上传合并复杂度最多单log,不能旋转 ...
随机推荐
- 牛客网试卷: 京东2019校招笔试Java开发工程师笔试题(1-)
1.在软件开发过程中,我们可以采用不同的过程模型,下列有关 增量模型描述正确的是() A 是一种线性开发模型,具有不可回溯性 B 把待开发的软件系统模块化,将每个模块作为一个增量组件,从而分批次地分析 ...
- JavaScrpt简单介绍
什么是javaScrpt javascript因为兼容于ECMA标准,因此也称为ECMAScript.JavaScript作为一种脚本语言,已经被广泛地应用于Web页面当中,通过嵌入HTML来实现各种 ...
- TeeChart设置图表的标题
TeeChart的图表的标题设置方法 tChart1.Header.Text = "图表"; tChart1.Header.Lines = new string[] { " ...
- 【附7】turbine
一.作用 聚集同一个微服务的相同的commandKey.Threadpool.commandGroupKey数据进行聚合 二.配置 1.集群(cluster)(turbine聚集数据的粒度) turb ...
- MapReduce程序(一)——wordCount
写在前面:WordCount的功能是统计输入文件中每个单词出现的次数.基本解决思路就是将文本内容切分成单词,将其中相同的单词聚集在一起,统计其数量作为该单词的出现次数输出. 1.MapReduce之w ...
- 2018/7/18Bad English
1 So instead of enjoying anime because it can portray interesting stories in a form that would be im ...
- UVa 10570 外星人聚会
https://vjudge.net/problem/UVA-10570 题意:输入1~n的排列,每次可以交换两个整数,求出最少交换次数使之变成有序的环状序列. 思路:主要的解题方法就是寻找置换环,举 ...
- C#高级编程第10版 note
泛型接口的抗变和协变 https://www.cnblogs.com/yanfang/p/6635302.html ①泛型接口,如果泛型类型前没有关键字out或者in来标注,则该泛型接口不支持抗变和协 ...
- vuex到底是个啥
vuex总结 Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化.Vuex 也集成到 Vue 的 ...
- Java jdbc访问sqlserver,oracle数据库 DEMO
1.JDBC访问Oracle数据库 public class Jdbc_Oracle { // 静态代码块,只会执行一次,类似C#静态构造方法 static { try { // 加载数据库驱动一次 ...