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,不能旋转 ...
随机推荐
- WideCharToMultiByte和MultiByteToWideChar函数的用法(转载)
出处:http://www.cnblogs.com/gakusei/articles/1585211.html 为了支持Unicode编码,需要多字节与宽字节之间的相互转换.这两个系统函数在使用时需要 ...
- Python3基础 os mkdir 创建一层文件夹 在有父目录的情况下创建子目录
Python : 3.7.0 OS : Ubuntu 18.04.1 LTS IDE : PyCharm 2018.2.4 Conda ...
- compile vi from source code
1.install ncurses library (vi depend on ncurses library) ./configure --prefix=/usr --with-termlib m ...
- spring集成mybatis后,打印SQL语句
网上说mybatis的早前版本配置打印sql还比较简单,在3.0.6之后配置方式修改了. 现在的spring-mybatis.xml配置如下: <bean id="sqlSession ...
- spring与spring-data-redis整合redis
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...
- 关于xargs cp中,如何确定拷贝的源和目的 (copied)
Seker: find . -name "*" |xargs cp ???? 这里 xargs cp 怎么区分cp源 和 cp目的 例如:想把 查询到的文件 都copy到/home ...
- springboot整合redis缓存
使用springBoot添加redis缓存需要在POM文件里引入 org.springframework.bootspring-boot-starter-cacheorg.springframewor ...
- Jsp基础语法(由简入杂)
JSP基础语法 一,JSP简介 Jsp是一个简化的Servlet设计,是在服务器端执行,他实现了再Java中使用HTML标签. Jsp是一种动态网页技术标准也是JAVAEE的标准 二,常见动态网站开发 ...
- 消息队列Kafka学习记录
Kafka其实只是众多消息队列中的一种,对于Kafka的具体释义我这里就不多说了,详见:http://baike.baidu.com/link?url=HWFYszYuMdP_lueFH5bmYnlm ...
- CSS实现和选择器
CSS实现和选择器 本课内容: 一.实现CSS四种方式 1,每个html标签中都有一个style样式属性,该属性的值就是css代码.(针对一个标签)2,使用style标签的方式. 一般都定义在head ...