文章目录

  • 题目描述
  • 解析
    • 删除区间
    • 插入数列
    • 修改&翻转
    • 区间和&最大子段和
  • 代码

传送门

题目描述

解析

阴间题…
这不是裸的板子吗?
国赛真的有人能把这题写出来吗…
应该算一道练习作用很强的题了
写完这题,各种平衡树维护区间操作的方法可以说是毕业了吧
题解封装一个split函数的实现技巧值得借鉴
总的来说就一句:不要忘记pushdown和pushup!

删除区间

设删除区间为[l,r]
先把l-1结点splay到根
再把r+1转到l-1的下面
这样[l,r]一定就在r+1的右儿子了
直接删掉即可

插入数列

先在外面用类似线段树的方法建一棵完全平衡的平衡树,然后当单点接到需要的位置(寻找位置与删除类似)

修改&翻转

上标记!
把对应区间转出来,打一个标记即可

区间和&最大子段和

区间和比较无脑
最大子段和做一个经典的小白逛公园就行了

说起来很轻松,本题代码实现在传标记时还是很恶心的
总结一些易错的问题:

  1. 再说一遍:不要漏掉pushup、pushdown!
  2. 注意本题最大子段和可以是负数,所以答案不能和0取max
  3. same操作可以用一个tag记录是否需要下传比laz记录下传的值更加舒服
  4. 反转的时候最大左子段和最大右子段也要交换
  5. 本题卡空间,因此需要动态分配点编号,注意分配之前确定标记都整干净了!
  6. 插入时把一个结点接到父亲上之前要把父亲的标记下传!
  7. 任何操作几乎都要splay一下沿路更新信息

都是辛酸泪…
上代码吧
(实现已经比较简洁了算上debug还是干到了小200行…)

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=2e6+100;
const int M=2e6+100;
const ll mod=1ll<<31;
ll read(){ll x=0,f=1;char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();};while(isdigit(c)){x=x*10+c-'0';c=getchar();};return x*f;
}
int n,m,k;
int fre[N],top;
int val[N],siz[N],f[N],lp[N],rp[N],mx[N],sum[N],r,rev[N],tag[N],tr[N][2];
#define ls (tr[x][0])
#define rs (tr[x][1])
void pushup(int x){if(!x) return;siz[x]=siz[ls]+siz[rs]+1;sum[x]=sum[ls]+sum[rs]+val[x];if(!ls&&!rs){lp[x]=rp[x]=max(0,val[x]);mx[x]=val[x];}else if(!ls){lp[x]=max(0,val[x]+lp[rs]);rp[x]=max(rp[rs],sum[rs]+val[x]);mx[x]=max(mx[rs],val[x]+lp[rs]);}else if(!rs){rp[x]=max(0,val[x]+rp[ls]);lp[x]=max(lp[ls],sum[ls]+val[x]);mx[x]=max(mx[ls],val[x]+rp[ls]);}else{lp[x]=max(lp[ls],sum[ls]+val[x]+lp[rs]);rp[x]=max(rp[rs],sum[rs]+val[x]+rp[ls]);mx[x]=max(rp[ls]+val[x]+lp[rs],max(mx[ls],mx[rs]));}
}
void rrr(int x){rev[x]^=1;swap(ls,rs);swap(lp[x],rp[x]);
}
void pushdown(int x){if(tag[x]){tag[x]=rev[x]=0;if(ls){val[ls]=val[x];tag[ls]=1;sum[ls]=siz[ls]*val[x];}if(rs){val[rs]=val[x];tag[rs]=1;sum[rs]=siz[rs]*val[x]; }if(val[x]>=0){if(ls) mx[ls]=lp[ls]=rp[ls]=sum[ls];if(rs) mx[rs]=lp[rs]=rp[rs]=sum[rs];}else{if(ls){lp[ls]=rp[ls]=0;mx[ls]=sum[ls];}if(rs){lp[rs]=rp[rs]=0;mx[rs]=sum[rs];}}}if(rev[x]){rev[x]=0;if(ls) rrr(ls);if(rs) rrr(rs);}
}
void dfs1(int x){if(!x) return;pushdown(x);dfs1(ls);printf("%d ",val[x]);dfs1(rs);pushup(x);
}
void dfs2(int x){if(!x) return;pushdown(x);printf("x=%d val=%d ls=%d rs=%d siz=%d\n",x,val[x],ls,rs,siz[x]);dfs2(ls);dfs2(rs);pushup(x);
}
void debug(int f){printf("------r=%d\n",r);if(f==1) dfs1(r);else dfs2(r);printf("\n\n");
}
int New(int v,int fa){int x=fre[top--];val[x]=mx[x]=sum[x]=v;lp[x]=rp[x]=max(0,v);f[x]=fa;siz[x]=1;tag[x]=rev[x]=0;return x;
}
#define which(x) (tr[f[x]][1]==x)
void rotate(int x){int fa=f[x],gfa=f[fa];pushdown(gfa);pushdown(fa);pushdown(x);int k=which(x),son=tr[x][k^1];f[x]=gfa;if(gfa) tr[gfa][which(fa)]=x;f[fa]=x;tr[x][k^1]=fa;f[son]=fa;tr[fa][k]=son;pushup(fa);pushup(x);pushup(gfa);
}
void splay(int x,int goal){if(x==goal) return;for(int fa;(fa=f[x])!=goal;rotate(x)){if(f[fa]!=goal)which(x)==which(fa)?rotate(fa):rotate(x);}if(!goal) r=x;
}
int a[N];
int build(int l,int r,int fa){if(l>r) return 0;int mid=(l+r)>>1;int x=New(a[mid],fa);tr[x][0]=build(l,mid-1,x);tr[x][1]=build(mid+1,r,x);pushup(x);
//  printf("l=%d r=%d x=%d pl=%d siz=%d\n",l,r,x,mid,siz[x]);return x;
}
int find(int x,int k){pushdown(x);if(siz[ls]>=k) return find(ls,k);else if(siz[ls]+1==k) return x;else return find(rs,k-siz[ls]-1);
}
int split(int l,int rr){int a=find(r,l-1);splay(a,0);int b=find(r,rr+1);splay(b,a);return tr[b][0];
}
void add(int x,int k,int s){pushdown(x);tr[x][k]=s;f[s]=x;pushup(x);
}
char s[150];
void ins(){int pos=read(),tot=read();pos++;for(int i=1;i<=tot;i++) a[i]=read();int now=build(1,tot,0);if(pos==1){int x=find(r,1);splay(x,0);int y=find(r,2);splay(y,x);add(y,0,now);splay(y,0);return;}int x=split(pos,pos);add(x,1,now);pushup(x);splay(now,0);
}
void save(int x){if(!x) return;fre[++top]=x;save(ls);save(rs);
}
void del(){int pos=read(),tot=read();pos++;int x=split(pos,pos+tot-1),fa=f[x];save(x);tr[fa][0]=0;pushup(fa);splay(fa,0);
}
void same(){int pos=read(),tot=read(),v=read();pos++;int x=split(pos,pos+tot-1);val[x]=v;tag[x]=1;sum[x]=siz[x]*v;lp[x]=rp[x]=max(0,sum[x]);splay(x,0);
}
void reverse(){int pos=read(),tot=read();pos++;int x=split(pos,pos+tot-1);rrr(x);//printf("x=%d\n",x);debug(2);splay(x,0);
}
void getsum(){int pos=read(),tot=read();pos++;int x=split(pos,pos+tot-1);printf("%d\n",sum[x]);
}
void maxsum(){printf("%d\n",mx[r]);
}
int main(){for(int i=500050;i>=1;i--) fre[++top]=i;n=read();m=read();for(int i=1;i<=n;i++) a[i]=read();r=build(1,n,0);splay(find(r,1),0);add(r,0,New(-20000,r));splay(find(r,n+1),0);add(r,1,New(-20000,r));//debug(1);for(int i=1;i<=m;i++){//  printf("-------------------------------------\n");scanf(" %s",s+1);if(s[1]=='I') ins();else if(s[1]=='D') del();else if(s[3]=='K') same();else if(s[1]=='R') reverse();else if(s[1]=='G') getsum();else maxsum();//debug(1);}return 0;
}
/*
*/

YBTOJ洛谷P2042:维护数列(平衡树)相关推荐

  1. [洛谷P3228] [HNOI2013]数列

    洛谷题目链接:[HNOI2013]数列 题目描述 小T最近在学着买股票,他得到内部消息:F公司的股票将会疯涨.股票每天的价格已知是正整数,并且由于客观上的原因,最多只能为N.在疯涨的K天中小T观察到: ...

  2. YBTOJ洛谷P4074:糖果公园(树上莫队)

    文章目录 解析 update: 代码 所谓树上莫队,就是在树上的莫队 (逃) 传送门 解析 似乎就是树上的这道题 考虑如何转化为序列问题呢? 考虑dfs序 但是又一个问题... 似乎这条链的dfs序不 ...

  3. YBTOJ洛谷P4551:最长异或路径(trie树)

    洛谷传送门 文章目录 题目描述 解析 代码 题目描述 解析 本题关键就在于一点: 若把每个点的深度dep[i]定义为从根到节点边权的异或和 那么i到j的路径异或和可以表示为: dep[i] ^ dep ...

  4. YBTOJ洛谷P4331:数字序列(左偏树)

    文章目录 题目描述 数据范围 解析 代码 题目描述 数据范围 n<=1e6n<=1e6n<=1e6 解析 先考虑简单情况 如果原数列是单调递增的,显然应该使bi=aib_i=a_ib ...

  5. 洛谷P2401 不等数列(线性DP)

    本题使用的是线性DP.就是DP数组难以思考,这里我直接给出 dp[i][j]:表示 1 ~ i 这 i 个数 , 其中j 个 " < " 有几种方法 假设我们已经把 n - ...

  6. ybtoj洛谷P3268:圆的异或并(扫描线)

    解析 很神奇的一道题. 关键条件:任意两个圆无交. 把一个圆分成上下两个圆弧,那么所有圆弧的高度关系不会发生变化. 所以可以开一个 set,维护一个从左往右扫的扫描线,按照当前扫描线的横坐标定义比较符 ...

  7. YBTOJ洛谷P2387: 魔法森林(LCT)

    解析 LCT从板子到算法的入门题吧 有一些不知道的很实用的技巧 把边按a排序从小到大加入边 那么我们只需要维护当前1-n路径上的b的最小值即可 如果这条边两端点本来不连通,就直接link 否则找到路径 ...

  8. YBTOJ洛谷P3195:玩具装箱(斜率优化dp)

    传送门 文章目录 前言 解析 代码 前言 斜率优化dp,就是利用斜率优化的dp (逃) 解析 第一道斜优的题 分析题目 设sumisum_isumi​为1-i的c的前缀和 容易写出dp转移式: dpi ...

  9. 【洛谷P3369】普通平衡树(splay)

    emmmmm直接丢代码了 #include<iostream> #include<cstdio> #include<cstring> #include<str ...

最新文章

  1. firefox下的调试工具
  2. JAVA数据结构 线性表的链式存储及其实现
  3. 46. Ext中namespace的作用(转)
  4. python bool转string_Python:可以返回boolean和string吗?
  5. Unix网络编程(六)高级I/O技术之复用技术 select
  6. php跳转分站,根据访客所在城市ip地址自动跳转到分站的php代码
  7. Java多线程学习二十三:什么是阻塞队列
  8. 浏览器兼容的JS写法总结
  9. python之解决Cannot uninstall ‘certifi‘问题
  10. (二)文档请求不同源之window.postMessage跨域
  11. 计算机视觉算法_RANSAC 估计
  12. Python歌词解析
  13. 表贴电阻尺寸与什么有关_贴片电阻、贴片电容规格、封装、尺寸、功率(转)
  14. wincc显示系统时间_Wincc的系统时间该如何用变量显示?
  15. Unit iptables.service could not be found
  16. 【基于Centos】驱动安装
  17. python2在线编译器_Skulpt搭建Python在线编译器(二):界面优化
  18. 三层交换 VLAN 互访配置
  19. 「业内分析」拉卡拉新商业模式的转化,拥抱下半场
  20. 招聘面试技巧(转载)

热门文章

  1. android pcm调节音量,调整PCM语音数据的音量
  2. python求导函数的值_python怎么实现函数求导
  3. hadoop 2.7 java_Hadoop2.7环境搭建---Java环境变量
  4. python中def和return是必须使用的保留字吗_Python 保留字和关键字的用法
  5. es6 ie不兼容 函数_ES6:什么是块级作用域?
  6. apt-get 更新指定软件_GrandPerspective for mac(磁盘管理软件)
  7. PAT乙级题目——1002写出这个数
  8. w7下如何安装linux双系统,ubuntu安装教程(下): 教你装win7+Ubuntu双系统
  9. core java面试题_CoreJava基础面试题
  10. Java Stack 类