题目链接

感谢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+倍增+重构)的更多相关文章

  1. 判断相同区间(lazy) 多校8 HDU 5828 Rikka with Sequence

    // 判断相同区间(lazy) 多校8 HDU 5828 Rikka with Sequence // 题意:三种操作,1增加值,2开根,3求和 // 思路:这题与HDU 4027 和HDU 5634 ...

  2. HDU 5828 Rikka with Sequence (线段树)

    Rikka with Sequence 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5828 Description As we know, Rik ...

  3. hdu 5828 Rikka with Sequence 线段树

    Rikka with Sequence 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5828 Description As we know, Rik ...

  4. hdu 5204 Rikka with sequence 智商不够系列

    Rikka with sequence Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.p ...

  5. HDU 5828 Rikka with Sequence(线段树 开根号)

    Rikka with Sequence Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Othe ...

  6. HDU 5828 Rikka with Sequence (线段树+剪枝优化)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5828 给你n个数,三种操作.操作1是将l到r之间的数都加上x:操作2是将l到r之间的数都开方:操作3是 ...

  7. HDU 5828 Rikka with Sequence(线段树)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5828 [题目大意] 给出一个数列,要求支持区间加法,区间开方和区间和查询操作. [题解] 考虑开方 ...

  8. HDU 5828 Rikka with Sequence(线段树区间加开根求和)

    Problem DescriptionAs we know, Rikka is poor at math. Yuta is worrying about this situation, so he g ...

  9. HDU 5828 Rikka with Sequence

    好久没写线段树了,这题作为一个回味.. 第一种操作的话,就是一个延迟标记. 第二种操作可以暴力更新下去,但是有一个优化,如果某区间内所有值都是一样的,或者最大值和最小值相差1,那么到此结束,不要继续往 ...

随机推荐

  1. 使用shell脚本常见的一些问题

    Jdk版本:jdk-8u102-linux-x64 Tomcat版本:apache-tomcat-7.0.92 Redis版本:redis-5.0.0 由于公司项目的需要,要在多台服务器上面部署一些应 ...

  2. ubuntu 编译安装 svn

    1,简单的安装svn (1)  sudo apt-get install subversion 但是此种方式,可能不能安装到当前最新的svn.如当前最新的版本是svn 1.8.9 ,但是 通过此种安装 ...

  3. 网页制作入门——HTML(2)编码与字符实体

    在上一期,我们顺口提到了——你写的网页在打开后,可能发现只是一串乱码.那么这是为什么呢? 这就是编码的神奇力量! 八卦的启示——什么是编码? 编码的思想,很早就在中国诞生了,从还不太明朗的结绳记事.算 ...

  4. 关于虚拟机docker 启动mysql 启动成功但未挂载到端口

    首先排查了防火墙和其他权限相关问题 然后检查了mysql 用户权限问题 docker logs 查看日志 正常应该是到3306 问题是我的mysql my.cnf 文件是挂在在本地.当第二次启动容器时 ...

  5. TCP和SSL TCP应用

    TCP和SSL TCP应用 对于普通开发者而言编写TCP应用通讯是一件相对复杂的工作,毕竟需要一系列的bytes操作:如果再针对SSL的安全性处理相信会把很多普通开发者拒之门外.为了简化这一问题Bee ...

  6. Hive 教程(五)-参数配置

    配置基本操作 hive> set; 查看所有配置hive> set key: 查看某个配置hive> set key value: 设置某个配置 我们可以看到一些 hadoop 的配 ...

  7. C语言实现远程代码注入

    #include <windows.h> #include <iostream> #define STRLEN 20 typedef struct _DATA { DWORD ...

  8. JDK SPI

    最近学习了JDK SPI   JDK SPI是什么 最近工作中听几个同事说了好几次SPI这个名词,虽然和我没关系,但是心里默默想还是学习一下,不然下次和我说到SPI,连是什么都不知道那就尴尬了. 所以 ...

  9. server001

  10. Linux 安装 python3.6 ,并且配置 Pycharm 远程连接开发

    Linux下安装Python3.6和第三方库   如果本机安装了python2,尽量不要管他,使用python3运行python脚本就好,因为可能有程序依赖目前的python2环境, 比如yum!!! ...