BZOJ1500:[NOI2005]维修数列
浅谈\(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]维修数列的更多相关文章
- [BZOJ1500][NOI2005]维修数列---解题报告
Portal Gun:[BZOJ1500][NOI2005]维修数列 有一段时间没写博客了,最近在刚数据结构......各种板子背得简直要起飞,题目也是一大堆做不完,这里就挑一道平衡树的题来写写好了 ...
- [BZOJ1500][NOI2005]维修数列 解题报告 Splay
Portal Gun:[BZOJ1500][NOI2005]维修数列 有一段时间没写博客了,最近在刚数据结构......各种板子背得简直要起飞,题目也是一大堆做不完,这里就挑一道平衡树的题来写写好了 ...
- bzoj千题计划221:bzoj1500: [NOI2005]维修数列(fhq treap)
http://www.lydsy.com/JudgeOnline/problem.php?id=1500 1.覆盖标记用INF表示无覆盖标记,要求可能用0覆盖 2.代表空节点的0号节点和首尾的两个虚拟 ...
- [bzoj1500][NOI2005]维修数列_非旋转Treap
维修数列 bzoj-1500 NOI-2005 题目大意:给定n个数,m个操作,支持:在指定位置插入一段数:删除一个数:区间修改:区间翻转.查询:区间和:全局最大子序列. 注释:$1\le n_{ma ...
- splay模板三合一 luogu2042 [NOI2005]维护数列/bzoj1500 [NOI2005]维修数列 | poj3580 SuperMemo | luogu3391 【模板】文艺平衡树(Splay)
先是维修数列 题解看这里,但是我写的跑得很慢 #include <iostream> #include <cstdio> using namespace std; int n, ...
- BZOJ1500[NOI2005]维修数列
Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目.第2行包含N个数字,描述初始时的数列.以下M行,每行一 ...
- BZOJ1500: [NOI2005]维修数列[splay ***]
1500: [NOI2005]维修数列 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 12278 Solved: 3880[Submit][Statu ...
- [bzoj1500][NOI2005]维修数列——splay
题目 题解 这道题可以说是数列问题的大BOSS,也算是这一周来学习splay等数据结构的一个总结. 我们一个一个地看这些操作. 对于操作1,我们首先建一棵子树,直接接上原树即可. 对于操作2,我们找到 ...
- BZOJ1500 [NOI2005]维修数列-fhq_Treap
题面见这里 反正是道平衡树,就拿 fhq_Treap 写了写... 这道题思路基本是围绕“用 Treap 维护中序遍历” 和 中序遍历的性质 来进行的操作 所以就可以类比线段树进行一些操作 1. 建树 ...
- BZOJ1500: [NOI2005]维修数列 [splay序列操作]【学习笔记】
以前写过这道题了,但我把以前的内容删掉了,因为现在感觉没法看 重写! 题意: 维护一个数列,支持插入一段数,删除一段数,修改一段数,翻转一段数,查询区间和,区间最大子序列 splay序列操作裸题 需要 ...
随机推荐
- web翻译——插件
很多时候,可能我们web项目中需要的只是机械式的翻译,并不需要什么利用xml或者js json等等实现逼真翻译,那样工作量太大.这时候可能你就需要这几款小工具来帮助你.当然,如果 对翻译或者你的项目外 ...
- 【selenium】Selenium基于Python3的Web自动化测试脚本在IE上运行慢的解决方法
阐述问题: 执行自动化脚本时,发现文本输入在IE浏览器上特别慢,这样大大降低了自动化效率 解决办法:原因是原先下载的IEDriverServer.exe为64位系统的IE,换为32位的IEDriver ...
- PowerBuilder -- Tab控件
在tab中关闭窗口 Close(tab_1.getparent()) 调整tab中的控件的tab oder 鼠标右键tabpage_1,选择 Tab Order菜单.
- eclipse maven 刷新报错
问题描述: An internal error occurred during: "Loading descriptor for cmbc_wms.".java.lang.Null ...
- C++刷题——2736: 指针练习--输出最大值
Description 採用指针法,输出10个整型数中的最大值和最小值 Input 10个整数 Output 最大值和最小值 Sample Input 2 6 3 8 1 5 7 0 4 9 Samp ...
- 如何在linux下解压缩rar格式的文件压缩包
##########################################################如何在linux下解压缩rar格式的文件压缩包#date:2014年2月15日22: ...
- android菜鸟学习笔记5----第一个android程序
程序功能:点击一个按钮,然后弹出一个提示信息 Step 1:在eclipse中新建一个android application project,在创建过程中不勾选create activity,这样就创 ...
- 九度OJ 1008:最短路径问题 (最短路)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:8064 解决:2685 题目描述: 给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费 ...
- Linux内核的编译安装
前言 Linux内核是Linux操作2347系统的核心,也是整个Linux功能体现的核心,就如同发动机在汽车中的重要性.内核主要功能包括进程管理.内存管理.文件管理.设备管理.网络管理等.Linux内 ...
- 【题解】[JSOI2008]最大数
[题解][P1198 JSOI2008]最大数 正难则反,意想不到. 这道题是动态让你维护一个数列,已经在数列里面的数据不做改变,每次在最后加上一个数,强制在线. 既然正着做很难,考虑如果时间倒流,不 ...