HDU - 6087 Rikka with Sequence (可持久化treap+倍增+重构)
感谢Dream_Lolita的题解,经过无数次失败的尝试之后终于AC了...
线段树是维护区间信息的强大工具,但它的形态是固定的,只支持修改和删除操作,不支持插入、反转、复制、分裂合并等操作,而treap支持。这道题有个区间复制的操作,因此只能用treap来代替了。
注意几个坑点:
1.对于操作2,当k<r-l+1时,不是将[l-k,r-k]中的元素直接替换到[l,r]上,而是将[l-k,l-1]中的元素复制多次再替换到[l,r]上,因此需要对[l-k,l-1]区间反复自我merge直至长度大于等于r-l+1,类似倍增的方式。
2.如果对每个结点设置一个静态的随机因子,那么对区间进行复制时,会产生大量重复的随机因子,严重影响树的平衡性。因此可以去掉随机因子,在对结点u,v进行merge的时候动态取一个随机数rnd,检查rnd%(siz[u]+siz[v])与siz[u]的关系来决定以哪种方式进行合并。考虑到评测OS是Windows,rand函数的上限只有2^15-1,因此可以采用rand()<<15|rand()的方法将两个rand函数拼凑起来,这样上限就扩大到2^30-1了。
3.操作3中的merge可以不用可持久化,但操作2中的merge必须可持久化,否则会出现莫名其妙的错误(这里查错查了很久,我暂时也说不清为什么)
4.本题对内存的限制非常严格,因此需要定期检查结点数量,如果快要超过内存上限了,就要对整个序列进行暴力重构。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=28e5+,inf=0x3f3f3f3f;
int ch[N][],val[N],siz[N],tot,n,m,rt,A,q[],nq;
ll sum[N];
#define l(u) ch[u][0]
#define r(u) ch[u][1]
int rnd() {return rand()<<|rand();}
int newnode(int x) {int u=++tot; val[u]=sum[u]=x,siz[u]=,l(u)=r(u)=; return u;}
int cpy(int u) {int w=++tot; val[w]=val[u],sum[w]=sum[u],siz[w]=siz[u],l(w)=l(u),r(w)=r(u); return w;}
void pu(int u) {siz[u]=siz[l(u)]+siz[r(u)]+,sum[u]=sum[l(u)]+sum[r(u)]+val[u];}
void sp(int w,int k,int& u,int& v) {
if(!w) {u=v=; return;}
if(k>=siz[l(w)]+)u=cpy(w),sp(r(w),k-(siz[l(w)]+),r(u),v),pu(u);
else v=cpy(w),sp(l(w),k,u,l(v)),pu(v);
}
void mg(int& w,int u,int v,int f=) {
if(!u||!v) {w=u|v; return;}
if(rnd()%(siz[u]+siz[v])<siz[u])w=(f?cpy(u):u),mg(r(w),r(u),v,f);
else w=(f?cpy(v):v),mg(l(w),u,l(v),f);
pu(w);
}
void upd(int& u,int l,int r,int k) {
int L,M,R,M2;
sp(u,l-,L,R),sp(L,l-k-,L,M);
while(siz[M]<r-l+)mg(M,M,M,);
sp(M,r-l+,M,M2),sp(u,r,L,R),sp(L,l-,L,M2);
mg(L,L,M,),mg(u,L,R,);
}
void upd2(int& u,int v,int l,int r) {
int L,M,R,M2;
sp(v,r,L,R),sp(L,l-,L,M);
sp(u,r,L,R),sp(L,l-,L,M2);
mg(L,L,M),mg(u,L,R);
}
ll qry(int& u,int l,int r) {
int L,M,R;
sp(u,r,L,R),sp(L,l-,L,M);
ll ret=sum[M];
mg(L,L,M),mg(u,L,R);
return ret;
}
void dfs(int u) {if(!u)return; dfs(l(u)),q[nq++]=val[u],dfs(r(u));}
void build(int& u,int l=,int r=n-) {
if(l>r) {u=; return;}
int mid=(l+r)>>;
u=newnode(q[mid]);
build(l(u),l,mid-),build(r(u),mid+,r),pu(u);
}
void rebuild() {tot=siz[A],nq=,dfs(rt),build(rt);}
int main() {
srand(time());
scanf("%d%d",&n,&m);
for(int i=; i<n; ++i)scanf("%d",&q[i]);
build(A),rt=A;
while(m--) {
int f,l,r,k;
scanf("%d%d%d",&f,&l,&r),l,r;
if(f==)scanf("%d",&k);
if(f==)printf("%lld\n",qry(rt,l,r));
else if(f==)upd(rt,l,r,k);
else if(f==)upd2(rt,A,l,r);
if(tot>)rebuild();
}
return ;
}
HDU - 6087 Rikka with Sequence (可持久化treap+倍增+重构)的更多相关文章
- 判断相同区间(lazy) 多校8 HDU 5828 Rikka with Sequence
// 判断相同区间(lazy) 多校8 HDU 5828 Rikka with Sequence // 题意:三种操作,1增加值,2开根,3求和 // 思路:这题与HDU 4027 和HDU 5634 ...
- HDU 5828 Rikka with Sequence (线段树)
Rikka with Sequence 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5828 Description As we know, Rik ...
- hdu 5828 Rikka with Sequence 线段树
Rikka with Sequence 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5828 Description As we know, Rik ...
- hdu 5204 Rikka with sequence 智商不够系列
Rikka with sequence Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.p ...
- HDU 5828 Rikka with Sequence(线段树 开根号)
Rikka with Sequence Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Othe ...
- HDU 5828 Rikka with Sequence (线段树+剪枝优化)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5828 给你n个数,三种操作.操作1是将l到r之间的数都加上x:操作2是将l到r之间的数都开方:操作3是 ...
- HDU 5828 Rikka with Sequence(线段树)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5828 [题目大意] 给出一个数列,要求支持区间加法,区间开方和区间和查询操作. [题解] 考虑开方 ...
- HDU 5828 Rikka with Sequence(线段树区间加开根求和)
Problem DescriptionAs we know, Rikka is poor at math. Yuta is worrying about this situation, so he g ...
- HDU 5828 Rikka with Sequence
好久没写线段树了,这题作为一个回味.. 第一种操作的话,就是一个延迟标记. 第二种操作可以暴力更新下去,但是有一个优化,如果某区间内所有值都是一样的,或者最大值和最小值相差1,那么到此结束,不要继续往 ...
随机推荐
- 使用shell脚本常见的一些问题
Jdk版本:jdk-8u102-linux-x64 Tomcat版本:apache-tomcat-7.0.92 Redis版本:redis-5.0.0 由于公司项目的需要,要在多台服务器上面部署一些应 ...
- ubuntu 编译安装 svn
1,简单的安装svn (1) sudo apt-get install subversion 但是此种方式,可能不能安装到当前最新的svn.如当前最新的版本是svn 1.8.9 ,但是 通过此种安装 ...
- 网页制作入门——HTML(2)编码与字符实体
在上一期,我们顺口提到了——你写的网页在打开后,可能发现只是一串乱码.那么这是为什么呢? 这就是编码的神奇力量! 八卦的启示——什么是编码? 编码的思想,很早就在中国诞生了,从还不太明朗的结绳记事.算 ...
- 关于虚拟机docker 启动mysql 启动成功但未挂载到端口
首先排查了防火墙和其他权限相关问题 然后检查了mysql 用户权限问题 docker logs 查看日志 正常应该是到3306 问题是我的mysql my.cnf 文件是挂在在本地.当第二次启动容器时 ...
- TCP和SSL TCP应用
TCP和SSL TCP应用 对于普通开发者而言编写TCP应用通讯是一件相对复杂的工作,毕竟需要一系列的bytes操作:如果再针对SSL的安全性处理相信会把很多普通开发者拒之门外.为了简化这一问题Bee ...
- Hive 教程(五)-参数配置
配置基本操作 hive> set; 查看所有配置hive> set key: 查看某个配置hive> set key value: 设置某个配置 我们可以看到一些 hadoop 的配 ...
- C语言实现远程代码注入
#include <windows.h> #include <iostream> #define STRLEN 20 typedef struct _DATA { DWORD ...
- JDK SPI
最近学习了JDK SPI JDK SPI是什么 最近工作中听几个同事说了好几次SPI这个名词,虽然和我没关系,但是心里默默想还是学习一下,不然下次和我说到SPI,连是什么都不知道那就尴尬了. 所以 ...
- server001
- Linux 安装 python3.6 ,并且配置 Pycharm 远程连接开发
Linux下安装Python3.6和第三方库 如果本机安装了python2,尽量不要管他,使用python3运行python脚本就好,因为可能有程序依赖目前的python2环境, 比如yum!!! ...