题目链接

感谢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. 如何在robotframework基础上使用数据驱动测试

    一.写在前面 robotframework是很好用的关键字驱动测试框架,但是在实际工作中也有些地方使用不便,比如在我们设计参数校验测试case时,往往只是想修改校验参数类型而不得不做大量复制粘贴操作, ...

  2. Git命令与介绍

    一. Git[命令与介绍] 1. 作用 可以用于个的项目版本控制和管理 目前多用于团队间的多人协作项目开发 2. 安装 l 安装包路径 l 安装 后的路径: 3. 工作流程 (1) 创建项目目录 在路 ...

  3. 【Python基础】lpthw - Exercise 46 项目骨架

    本节将会介绍如何构建一个项目骨架目录.骨架目录中会包含项目文件布局.自动测试代码.模块及安装脚本. 一.环境配置(win10) 1. 检查并确认自己只安装了一个python版本. cd ~ pytho ...

  4. Linux中命令别名alias与命令替换

    当我们使用bash进行一些操作的时候,希望一些较为长的命令使用一些短的命令即可完成输入运行的话,我们就可以使用alias命令别名来帮助我们完成这个任务 alias作为一个bash的内置命令,具有一定的 ...

  5. 【机器学习】Jackknife,Bootstraping, bagging, boosting, AdaBoosting, Rand forest 和 gradient boosting

    Jackknife,Bootstraping, bagging, boosting, AdaBoosting, Rand forest 和 gradient boosting 这些术语,我经常搞混淆, ...

  6. springboot 极简使用例子: redis,MySql数据库,日志,netty,打包和运行

    配置 创建项目的时候选择 application.yml内容如下 spring: redis: host: 127.0.0.1 port: 6379 database: 0 datasource: d ...

  7. ASP.NET Core WebApi使用Swagger

    先在项目中引用Nuget包 Install-Package Swashbuckle.AspNetCore 安装之后需要在Startup.cs文件加入如下代码 public void Configure ...

  8. Laravel关联模型

    public $timestamps = false;//不存时间 1.多对多关联.如收藏.用户表users,产品表products,收藏中间表user_favorite_products.那么在用户 ...

  9. unsigned char 与unsigned long互换

    unsigned long UCharToULong(unsigned char * pucVar ){unsigned long ulTemp=0;ulTemp=(unsigned long)(*p ...

  10. 区间最值的优秀数据结构---ST表

    ST表,听起来高大上,实际上限制非常多,仅仅可以求最值问题: 为什么?先从原理看起: st表运用了倍增的思想:st[i][j] = min(st[i][j - 1],st[i + 2^(j - 1)) ...