浅谈\(splay\):https://www.cnblogs.com/AKMer/p/9979592.html

浅谈\(fhq\)_\(treap\):https://www.cnblogs.com/AKMer/p/9981274.html

题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=1500

究极无敌大模板题,记得要写垃圾回收。

时间复杂度:\(O((n+m)logn)\)

空间复杂度:\(O(n)\)

\(splay\)代码如下:

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std; const int maxn=5e5+5,inf=1e9; char s[20];
int a[maxn];
int n,m,pos,tot; int read() {
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
} struct Splay {
int root;
int dust[maxn],top;
int val[maxn],sum[maxn];
bool rev[maxn],cov[maxn];
int mx[maxn],lmx[maxn],rmx[maxn];
int siz[maxn],fa[maxn],son[maxn][2]; void clear(int u) {
rev[u]=cov[u]=0;
son[u][0]=son[u][1]=0;
} void update(int u) {
int ls=son[u][0],rs=son[u][1];
siz[u]=siz[ls]+1+siz[rs];
sum[u]=sum[ls]+val[u]+sum[rs];
lmx[u]=max(lmx[ls],sum[ls]+val[u]+lmx[rs]);
rmx[u]=max(rmx[rs],sum[rs]+val[u]+rmx[ls]);
mx[u]=max(max(mx[ls],mx[rs]),rmx[ls]+val[u]+lmx[rs]);
} int build(int l,int r,int lst) {
if(r<l)return 0;
if(l==r) {
int id=dust[top--];
siz[id]=1,fa[id]=lst;
lmx[id]=rmx[id]=max(0,a[l]);
val[id]=sum[id]=mx[id]=a[l];
return id;
}
int mid=(l+r)>>1,id=dust[top--];
val[id]=a[mid],fa[id]=lst;
son[id][0]=build(l,mid-1,id);
son[id][1]=build(mid+1,r,id);
update(id);return id;
} void prepare() {
mx[0]=-inf;
for(int i=1;i<=500002;i++)
dust[++top]=i;
root=build(1,n+2,0);
} void make_cov_tag(int u,int v) {
if(!u)return;
cov[u]=1,val[u]=v,sum[u]=siz[u]*v;
if(v>0)lmx[u]=rmx[u]=mx[u]=siz[u]*v;
else lmx[u]=rmx[u]=0,mx[u]=v;
} void make_rev_tag(int u) {
if(!u)return;
swap(lmx[u],rmx[u]);
rev[u]^=1,swap(son[u][0],son[u][1]);
} void push_down(int u) {
if(cov[u]) {
make_cov_tag(son[u][0],val[u]);
make_cov_tag(son[u][1],val[u]);
cov[u]=0;
}
if(rev[u]) {
make_rev_tag(son[u][0]);
make_rev_tag(son[u][1]);
rev[u]=0;
}
} int find(int u,int rk) {
push_down(u);
if(siz[son[u][0]]+1==rk)return u;
if(siz[son[u][0]]>=rk)return find(son[u][0],rk);
return find(son[u][1],rk-siz[son[u][0]]-1);
} int t(int u) {return son[fa[u]][1]==u;} void rotate(int u) {
int ret=t(u),f=fa[u],s=son[u][ret^1];
son[f][ret]=s;if(s)fa[s]=f;son[u][ret^1]=f;
fa[u]=fa[f];if(fa[f])son[fa[f]][t(f)]=u;
fa[f]=u;update(f),update(u);
} void splay(int goal,int u) {
int tmp=fa[goal];
while(fa[u]!=tmp) {
if(fa[fa[u]]!=tmp) {
if(t(fa[u])==t(u))rotate(fa[u]);
else rotate(u);
}
rotate(u);
}
if(!tmp)root=u;
} void recycle(int u) {
if(!u)return;
dust[++top]=u;
recycle(son[u][0]);
recycle(son[u][1]);
clear(u);
} void ins(int pos) {
for(int i=1;i<=tot;i++)a[i]=read();
int u1=find(root,pos),u2=find(root,pos+1);
splay(root,u1),splay(son[u1][1],u2);
son[u2][0]=build(1,tot,u2);
update(u2),update(u1);
} void del(int l,int r) {
int u1=find(root,l-1),u2=find(root,r+1);
splay(root,u1),splay(son[u1][1],u2);
int tmp=son[u2][0];
son[u2][0]=fa[tmp]=0;
recycle(tmp);
update(u2),update(u1);
} void cover(int l,int r,int v) {
int u1=find(root,l-1),u2=find(root,r+1);
splay(root,u1),splay(son[u1][1],u2);
make_cov_tag(son[u2][0],v);
update(u2),update(u1);
} void rever(int l,int r) {
int u1=find(root,l-1),u2=find(root,r+1);
splay(root,u1),splay(son[u1][1],u2);
make_rev_tag(son[u2][0]);
update(u2),update(u1);
} int query(int l,int r) {
int u1=find(root,l-1),u2=find(root,r+1);
splay(root,u1),splay(son[u1][1],u2);
return sum[son[u2][0]];
}
}T; int main() {
n=read(),m=read();
for(int i=2;i<=n+1;i++)
a[i]=read();
a[1]=a[n+2]=-inf,T.prepare();
for(int i=1;i<=m;i++) {
scanf("%s",s+1);
if(s[1]!='M'||s[4]!='-')
pos=read()+1,tot=read();
if(s[1]=='I')T.ins(pos);
if(s[1]=='D')T.del(pos,pos+tot-1);
if(s[1]=='M'&&s[4]=='E') {
int c=read();
T.cover(pos,pos+tot-1,c);
}
if(s[1]=='R')T.rever(pos,pos+tot-1);
if(s[1]=='G')printf("%d\n",T.query(pos,pos+tot-1));
if(s[1]=='M'&&s[4]=='-')printf("%d\n",T.mx[T.root]);
}
return 0;
}

\(fhq\)_\(treap\)版代码如下:

#include <ctime>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef pair<int,int> pii; const int maxn=5e5+5,inf=1e9; char s[20];
int a[maxn];
int n,m,pos,tot; int read() {
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
} struct fhq_treap {
int root,top;
int dust[maxn];
bool cov[maxn],rev[maxn];
int fix[maxn],son[maxn][2];
int mx[maxn],lmx[maxn],rmx[maxn];
int val[maxn],sum[maxn],siz[maxn]; void update(int u) {
int ls=son[u][0],rs=son[u][1];
siz[u]=siz[ls]+1+siz[rs];
sum[u]=sum[ls]+val[u]+sum[rs];
lmx[u]=max(lmx[ls],sum[ls]+val[u]+lmx[rs]);
rmx[u]=max(rmx[rs],sum[rs]+val[u]+rmx[ls]);
mx[u]=max(max(mx[ls],mx[rs]),rmx[ls]+val[u]+lmx[rs]);
} int build(int l,int r) {
if(r<l)return 0;
if(l==r) {
int id=dust[top--];
fix[id]=rand(),siz[id]=1;
mx[id]=val[id]=sum[id]=a[l];
lmx[id]=rmx[id]=max(0,a[l]);
return id;
}
int mid=(l+r)>>1,id=dust[top--];
fix[id]=rand(),val[id]=a[mid];
son[id][0]=build(l,mid-1);
son[id][1]=build(mid+1,r);
update(id);return id;
} void prepare() {
mx[0]=-inf;
for(int i=1;i<=500000;i++)
dust[++top]=i;
root=build(1,n);
} void make_cov_tag(int u,int v) {
if(!u)return;
cov[u]=1,val[u]=v,sum[u]=siz[u]*v;
if(v>0)mx[u]=lmx[u]=rmx[u]=sum[u];
else mx[u]=v,lmx[u]=rmx[u]=0;
} void make_rev_tag(int u) {
if(!u)return;
rev[u]^=1,swap(lmx[u],rmx[u]);
swap(son[u][0],son[u][1]);
} void push_down(int u) {
if(cov[u]) {
make_cov_tag(son[u][0],val[u]);
make_cov_tag(son[u][1],val[u]);
cov[u]=0;
}
if(rev[u]) {
make_rev_tag(son[u][0]);
make_rev_tag(son[u][1]);
rev[u]=0;
}
} pii split(int u,int rk) {
if(!rk)return make_pair(0,u);
if(rk==siz[u])return make_pair(u,0);
push_down(u);
if(siz[son[u][0]]>=rk) {
pii tmp=split(son[u][0],rk);
son[u][0]=tmp.second,update(u);
return make_pair(tmp.first,u);
}
else {
pii tmp=split(son[u][1],rk-siz[son[u][0]]-1);
son[u][1]=tmp.first,update(u);
return make_pair(u,tmp.second);
}
} int merge(int a,int b) {
if(!a||!b)return a+b;
push_down(a),push_down(b);
if(fix[a]>fix[b])return son[a][1]=merge(son[a][1],b),update(a),a;
else return son[b][0]=merge(a,son[b][0]),update(b),b;
} void ins(int pos) {
for(int i=1;i<=tot;i++)
a[i]=read();
pii tmp=split(root,pos);
root=merge(merge(tmp.first,build(1,tot)),tmp.second);
} void recycle(int u) {
if(!u)return;
dust[++top]=u;
recycle(son[u][0]),recycle(son[u][1]);
son[u][0]=son[u][1]=0,rev[u]=cov[u]=0;
} void del(int l,int r) {
pii tmp1=split(root,r);
pii tmp2=split(tmp1.first,l-1);
root=merge(tmp2.first,tmp1.second);
recycle(tmp2.second);
} void cover(int l,int r) {
int v=read();
pii tmp1=split(root,r);
pii tmp2=split(tmp1.first,l-1);
make_cov_tag(tmp2.second,v);
root=merge(merge(tmp2.first,tmp2.second),tmp1.second);
} void rever(int l,int r) {
pii tmp1=split(root,r);
pii tmp2=split(tmp1.first,l-1);
make_rev_tag(tmp2.second);
root=merge(merge(tmp2.first,tmp2.second),tmp1.second);
} int query(int l,int r) {
pii tmp1=split(root,r);
pii tmp2=split(tmp1.first,l-1);
int res=sum[tmp2.second];
root=merge(merge(tmp2.first,tmp2.second),tmp1.second);
return res;
}
}T; int main() {
srand(time(0));
n=read(),m=read();
for(int i=1;i<=n;i++)
a[i]=read();
T.prepare();
for(int i=1;i<=m;i++) {
scanf("%s",s+1);
if(s[1]!='M'||s[4]!='-')
pos=read(),tot=read();
if(s[1]=='I')T.ins(pos);
if(s[1]=='D')T.del(pos,pos+tot-1);
if(s[1]=='M'&&s[4]=='E')T.cover(pos,pos+tot-1);
if(s[1]=='R')T.rever(pos,pos+tot-1);
if(s[1]=='G')printf("%d\n",T.query(pos,pos+tot-1));
if(s[1]=='M'&&s[4]=='-')printf("%d\n",T.mx[T.root]);
}
return 0;
}

BZOJ1500:[NOI2005]维修数列的更多相关文章

  1. [BZOJ1500][NOI2005]维修数列---解题报告

    Portal Gun:[BZOJ1500][NOI2005]维修数列 有一段时间没写博客了,最近在刚数据结构......各种板子背得简直要起飞,题目也是一大堆做不完,这里就挑一道平衡树的题来写写好了 ...

  2. [BZOJ1500][NOI2005]维修数列 解题报告 Splay

    Portal Gun:[BZOJ1500][NOI2005]维修数列 有一段时间没写博客了,最近在刚数据结构......各种板子背得简直要起飞,题目也是一大堆做不完,这里就挑一道平衡树的题来写写好了 ...

  3. bzoj千题计划221:bzoj1500: [NOI2005]维修数列(fhq treap)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1500 1.覆盖标记用INF表示无覆盖标记,要求可能用0覆盖 2.代表空节点的0号节点和首尾的两个虚拟 ...

  4. [bzoj1500][NOI2005]维修数列_非旋转Treap

    维修数列 bzoj-1500 NOI-2005 题目大意:给定n个数,m个操作,支持:在指定位置插入一段数:删除一个数:区间修改:区间翻转.查询:区间和:全局最大子序列. 注释:$1\le n_{ma ...

  5. splay模板三合一 luogu2042 [NOI2005]维护数列/bzoj1500 [NOI2005]维修数列 | poj3580 SuperMemo | luogu3391 【模板】文艺平衡树(Splay)

    先是维修数列 题解看这里,但是我写的跑得很慢 #include <iostream> #include <cstdio> using namespace std; int n, ...

  6. BZOJ1500[NOI2005]维修数列

    Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目.第2行包含N个数字,描述初始时的数列.以下M行,每行一 ...

  7. BZOJ1500: [NOI2005]维修数列[splay ***]

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 12278  Solved: 3880[Submit][Statu ...

  8. [bzoj1500][NOI2005]维修数列——splay

    题目 题解 这道题可以说是数列问题的大BOSS,也算是这一周来学习splay等数据结构的一个总结. 我们一个一个地看这些操作. 对于操作1,我们首先建一棵子树,直接接上原树即可. 对于操作2,我们找到 ...

  9. BZOJ1500 [NOI2005]维修数列-fhq_Treap

    题面见这里 反正是道平衡树,就拿 fhq_Treap 写了写... 这道题思路基本是围绕“用 Treap 维护中序遍历” 和 中序遍历的性质 来进行的操作 所以就可以类比线段树进行一些操作 1. 建树 ...

  10. BZOJ1500: [NOI2005]维修数列 [splay序列操作]【学习笔记】

    以前写过这道题了,但我把以前的内容删掉了,因为现在感觉没法看 重写! 题意: 维护一个数列,支持插入一段数,删除一段数,修改一段数,翻转一段数,查询区间和,区间最大子序列 splay序列操作裸题 需要 ...

随机推荐

  1. mybatis的拦截器及分页机制

    https://blog.csdn.net/ssuperlg/article/details/79847889

  2. 【C/C++】高亮C++中函数的重写——函数名相同?参数列表相同?返回值相同?

    C++的重载给人留下了非常深刻的影响,原因是重载的条件很值得注意:函数名相同,参数列表不相同的两个函数构成重载函数,而无关乎二者的返回值. 但是C++中的函数重写又是另一码事.标准规定:只要函数名相同 ...

  3. Linux下实现RAID

    一.实验目的 1.掌握Linux系统下软RAID的实现方法: 2.掌握RAID5的配置过程: 3. 通过实验熟悉RAID.5的特点. 二.实验内容及步骤 1.在VMware中创建一台Linux. 2. ...

  4. JVM内存布局及GC知识回顾

    注:本文篇幅较长,且需要有一定的java基础,建议各位看官,备好瓜子.饮料.小板凳,摆个让自己舒服的姿势,慢慢细看^_^, 文中所有素材,均来自互联网,本人只是详细梳理了一遍,形成此文. 一.JVM运 ...

  5. npm ERR! fatal: unable to connect to github.com

    https://blog.csdn.net/baidu_30809315/article/details/86520093 git config --global url."https:// ...

  6. 软件测试人员需要精通的开发语言(5)--- Python

    Python语言,也算是后起之秀,多平台的应用也让它成为万能的脚本语言,应用于各种架构各种工具,得到广泛应用.而且如今比较火热的行业,软件爬虫,多半是用Python开发的.因为Python是一种开放源 ...

  7. 【BZOJ4945】[Noi2017]游戏 2-SAT

    [BZOJ4945][Noi2017]游戏 题目描述 题解:2-SAT学艺不精啊! 这题一打眼看上去是个3-SAT?哎?3-SAT不是NPC吗?哎?这题x怎么只有8个?暴力走起! 因为x要么不是A要么 ...

  8. 【BZOJ3956】Count 主席树+单调栈

    [BZOJ3956]Count Description Input Output Sample Input 3 2 0 2 1 2 1 1 1 3 Sample Output 0 3 HINT M,N ...

  9. 发送邮件 Email(java实现)

    //发送邮件 private static void sendMail(String mail, String mailContext) { try { //获取文本中html的内容 并动态替换并显示 ...

  10. git修改commit说明

    当发现说明写错了时,执行git commit --amend,然后修改说明即可.