终于yy过去了

撒花

调了一天半,出了无数锅

以下是出锅列表

  • rotate的时候要判断父亲节点的父亲节点是否存在
  • rotate的时候记得修改节点的父亲信息
  • pushdown的时候注意特判有无左右子树
  • 本题最大子段和要求至少要有一个数字
  • splay的每个节点中都存有一个点的权值,和线段树不同
  • lx和rx可以为0
  • 初始化哨兵节点的时候,哨兵节点的权值为-INF,否则会影响到最大子段和的询问
  • splay操作时候特判父亲节点的父亲节点是否是goal节点和父亲节点是否是goal节点,每次rorate后维护父亲的值
  • 区间整体偏移加一不要忘记
  • val>=1不要打成tag>=1
  • newNode的时候lx,rx赋值成max(0,val)
  • findkth的时候注意pushdown
  • erase,makesame和insert后注意pushup
  • makesame时不仅要修改对应标记,还要修改对应节点的数值
  • Reverse的时候翻转lx,rx,还要翻转两颗子树,tag用^的方式下传,因为翻转两次等于没有翻转
  • 回收节点时,标记记得清空

    我果然还是太弱了

    放一下丑陋无比的代码
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
struct SPTNode{
int son[2],val,sz,fa,Lmax,Rmax,partMax,Sum,SwapTag,SameTag;
}SPT[550100];
queue<int> frees;
int root,NumToIns[550100],n,m,a[550100];
bool isrl(int o){//false is left : true is right
return SPT[SPT[o].fa].son[1]==o;
}
void pushup(int o){
SPT[o].sz=SPT[SPT[o].son[0]].sz+SPT[SPT[o].son[1]].sz+1;
SPT[o].Sum=SPT[SPT[o].son[0]].Sum+SPT[SPT[o].son[1]].Sum+SPT[o].val;
SPT[o].partMax=max(SPT[SPT[o].son[0]].partMax,max(SPT[SPT[o].son[1]].partMax,SPT[SPT[o].son[0]].Rmax+SPT[SPT[o].son[1]].Lmax+SPT[o].val));
SPT[o].Lmax=max(SPT[SPT[o].son[0]].Lmax,SPT[SPT[o].son[1]].Lmax+SPT[SPT[o].son[0]].Sum+SPT[o].val);
SPT[o].Rmax=max(SPT[SPT[o].son[1]].Rmax,SPT[SPT[o].son[0]].Rmax+SPT[SPT[o].son[1]].Sum+SPT[o].val);
}
void pushdown(int o){
if(o&&SPT[o].SameTag){
if(SPT[o].son[0]){
SPT[SPT[o].son[0]].SameTag=1;
SPT[SPT[o].son[0]].val=SPT[o].val;
SPT[SPT[o].son[0]].Sum=SPT[SPT[o].son[0]].val*SPT[SPT[o].son[0]].sz;
if(SPT[o].val>=0)
SPT[SPT[o].son[0]].Lmax=SPT[SPT[o].son[0]].Rmax=SPT[SPT[o].son[0]].partMax=SPT[SPT[o].son[0]].Sum;
else{
SPT[SPT[o].son[0]].Lmax=SPT[SPT[o].son[0]].Rmax=0;
SPT[SPT[o].son[0]].partMax=SPT[SPT[o].son[0]].val;
}
}
if(SPT[o].son[1]){
SPT[SPT[o].son[1]].SameTag=1;
SPT[SPT[o].son[1]].val=SPT[o].val;
SPT[SPT[o].son[1]].Sum=SPT[SPT[o].son[1]].val*SPT[SPT[o].son[1]].sz;
if(SPT[o].val>=0)
SPT[SPT[o].son[1]].Lmax=SPT[SPT[o].son[1]].Rmax=SPT[SPT[o].son[1]].partMax=SPT[SPT[o].son[1]].Sum;
else{
SPT[SPT[o].son[1]].Lmax=SPT[SPT[o].son[1]].Rmax=0;
SPT[SPT[o].son[1]].partMax=SPT[SPT[o].son[1]].val;
}
}
SPT[o].SameTag=SPT[o].SwapTag=0;
}
else if(o&&SPT[o].SwapTag){
if(SPT[o].son[0]){
SPT[SPT[o].son[0]].SwapTag^=1;
swap(SPT[SPT[o].son[0]].Lmax,SPT[SPT[o].son[0]].Rmax);
swap(SPT[SPT[o].son[0]].son[0],SPT[SPT[o].son[0]].son[1]);
}
if(SPT[o].son[1]){
SPT[SPT[o].son[1]].SwapTag^=1;
swap(SPT[SPT[o].son[1]].Lmax,SPT[SPT[o].son[1]].Rmax);
swap(SPT[SPT[o].son[1]].son[0],SPT[SPT[o].son[1]].son[1]);
}
SPT[o].SwapTag=0;
}
}
void rorate(int o){
int f=SPT[o].fa;
int g=SPT[f].fa;
int which=isrl(o);
pushdown(f);
pushdown(o);
SPT[f].son[which]=SPT[o].son[which^1];
SPT[SPT[f].son[which]].fa=f;
SPT[o].son[which^1]=f;
SPT[f].fa=o;
SPT[o].fa=g;
if(g)
SPT[g].son[SPT[g].son[1]==f]=o;
pushup(f);
pushup(o);
}
void splay(int o,int goal){
for(int f;(f=SPT[o].fa)!=goal;rorate(o))
if(SPT[f].fa!=goal)
rorate(isrl(f)==isrl(o)?f:o);
if(goal==0)
root=o;
} int finds(int o,int kth){
if(!o)
return 0;
pushdown(o);
if(kth==SPT[SPT[o].son[0]].sz+1)
return o;
if(kth<=SPT[SPT[o].son[0]].sz)
return finds(SPT[o].son[0],kth);
else
return finds(SPT[o].son[1],kth-SPT[SPT[o].son[0]].sz-1);
}
int newNode(int fax,int valx){
int num=frees.front();
frees.pop();
SPT[num].Lmax=SPT[num].Rmax=max(0,valx);
SPT[num].partMax=valx;
SPT[num].SameTag=SPT[num].SwapTag=0;
SPT[num].Sum=valx;
SPT[num].fa=fax;
SPT[num].son[0]=SPT[num].son[1]=0;
SPT[num].sz=1;
SPT[num].val=valx;
return num;
}
void init(void){
for(int i=1;i<=550000;i++)
frees.push(i);
}
int build(int l,int r,int a[],int fa){
if(r<l)
return 0;
int mid=(l+r)>>1;
int numx=newNode(fa,a[mid]);
SPT[numx].son[0]=build(l,mid-1,a,numx);
SPT[numx].son[1]=build(mid+1,r,a,numx);
pushup(numx);
return numx;
}
void insert(void){
int posi,tot;
scanf("%d %d",&posi,&tot);
for(int i=1;i<=tot;i++)
scanf("%d",&NumToIns[i]);
int mergeroot=build(1,tot,NumToIns,0);
int L=posi,R=posi+1;
int lxx=finds(root,L+1),rxx=finds(root,R+1);
splay(lxx,0);
splay(rxx,lxx);
pushdown(root);
pushdown(SPT[root].son[1]);
SPT[SPT[root].son[1]].son[0]=mergeroot;
SPT[mergeroot].fa=SPT[root].son[1];
pushup(SPT[root].son[1]);
pushup(root);
}
void dfsRec(int u){
if(!u)
return;
pushdown(u);
frees.push(u);
dfsRec(SPT[u].son[0]);
dfsRec(SPT[u].son[1]);
}
void del(void){
int posi,tot;
scanf("%d %d",&posi,&tot);
int L=posi,R=posi+tot;
int lxx=finds(root,L),rxx=finds(root,R+1);
splay(lxx,0);
splay(rxx,lxx);
pushdown(root);
pushdown(SPT[root].son[1]);
dfsRec(SPT[SPT[root].son[1]].son[0]);
SPT[SPT[root].son[1]].son[0]=0;
pushup(SPT[root].son[1]);
pushup(root);
}
void swapArr(void){
int posi,tot;
scanf("%d %d",&posi,&tot);
int L=posi,R=posi+tot;
int lxx=finds(root,L),rxx=finds(root,R+1);
splay(lxx,0);
splay(rxx,lxx);
pushdown(root);
pushdown(SPT[root].son[1]);
if(!SPT[SPT[SPT[root].son[1]].son[0]].SameTag){
SPT[SPT[SPT[root].son[1]].son[0]].SwapTag^=1;
swap(SPT[SPT[SPT[root].son[1]].son[0]].son[0],SPT[SPT[SPT[root].son[1]].son[0]].son[1]);
swap(SPT[SPT[SPT[root].son[1]].son[0]].Lmax,SPT[SPT[SPT[root].son[1]].son[0]].Rmax);
pushup(SPT[root].son[1]);
pushup(root);
}
}
void QuerySum(void){
int posi,tot;
scanf("%d %d",&posi,&tot);
int L=posi,R=posi+tot;
int lxx=finds(root,L),rxx=finds(root,R+1);
splay(lxx,0);
splay(rxx,lxx);
pushdown(root);
pushdown(SPT[root].son[1]);
printf("%d\n",SPT[SPT[SPT[root].son[1]].son[0]].Sum);
}
void QueryPartMax(void){
printf("%d\n",SPT[root].partMax);
}
void MakeTheSame(void){
int posi,tot,cx;
scanf("%d %d %d",&posi,&tot,&cx);
int L=posi,R=posi+tot;
int lxx=finds(root,L),rxx=finds(root,R+1);
splay(lxx,0);
splay(rxx,lxx);
pushdown(root);
pushdown(SPT[root].son[1]);
SPT[SPT[SPT[root].son[1]].son[0]].SameTag=1;
SPT[SPT[SPT[root].son[1]].son[0]].val=cx;
SPT[SPT[SPT[root].son[1]].son[0]].Sum=cx*SPT[SPT[SPT[root].son[1]].son[0]].sz;
if(cx>=0)
SPT[SPT[SPT[root].son[1]].son[0]].Lmax=SPT[SPT[SPT[root].son[1]].son[0]].Rmax=SPT[SPT[SPT[root].son[1]].son[0]].partMax=SPT[SPT[SPT[root].son[1]].son[0]].Sum;
else{
SPT[SPT[SPT[root].son[1]].son[0]].Lmax=SPT[SPT[SPT[root].son[1]].son[0]].Rmax=0;
SPT[SPT[SPT[root].son[1]].son[0]].partMax=cx;
}
pushup(SPT[root].son[1]);
pushup(root);
}
void debug(void){
int xxxx;
printf("getL=");
scanf("%d",&xxxx);
for(int posi=1;posi<=xxxx;posi++){
int L=posi,R=posi+1;
int lxx=finds(root,L),rxx=finds(root,R+1);
splay(lxx,0);
splay(rxx,lxx);
pushdown(root);
printf("%d ",SPT[SPT[SPT[root].son[1]].son[0]].Sum);
}
printf("\n");
}
int main(){
init();
scanf("%d %d",&n,&m);
for(int i=2;i<=n+1;i++)
scanf("%d",&a[i]);
a[1]=-0x3f3f3f3f;
a[n+2]=-0x3f3f3f3f;
SPT[0].partMax=-0x3f3f3f3f;
root=build(1,n+2,a,0);
char opt[20];
for(int i=1;i<=m;i++){
// debug();
scanf("%s",opt);
if(opt[0]=='I'){
insert();
}
else if(opt[0]=='D'){
del();
}
else if(opt[0]=='M'&&opt[2]=='K'){
MakeTheSame();
}
else if(opt[0]=='R'){
swapArr();
}
else if(opt[0]=='G'){
QuerySum();
}
else if(opt[0]=='M'&&opt[2]=='X'){
QueryPartMax();
}
}
return 0;
}

p2042 维修数列(SPLAY)的更多相关文章

  1. 【BZOJ-1500】维修数列 Splay

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

  2. bzoj 1500: [NOI2005]维修数列 splay

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 6556  Solved: 1963[Submit][Status ...

  3. [BZOJ 1500]维修数列 [Splay Tree从进阶到住院]

    历尽艰辛终于A掉了这题QwQ 贴COGS评论区几句话=.= 策爷:"splay/块状链表的自虐题.".深刻理解到如果没有M倾向就不要去写这题了.. -Chenyao2333 记得b ...

  4. BZOJ 1500: [NOI2005]维修数列 (splay tree)

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 4229  Solved: 1283[Submit][Status ...

  5. 【BZOJ1500】[NOI2005]维修数列 Splay

    [BZOJ1500][NOI2005]维修数列 Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目.第2行 ...

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

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

  7. [NOI2005]维修数列 Splay tree 区间反转,修改,求和,求最值

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1500 Description Input 输入文件的第1行包含两个数N和M,N表示初始时数 ...

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

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

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

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

随机推荐

  1. JQuery基本知识(3)

    JQuery基本知识(3) 一.JQuery拥有可操作HTML元素和属性的强大方法. 1.JQuery DOM操作(DOM文档对象模型) 获取内容的方法: text():设置或返回所选元素的文本内容 ...

  2. php aes128加密

    //[加密数据]AES 128 ECB模式 public function aesEncrypt($str){ $screct_key = Yii::$app->params['encryptK ...

  3. 对象的copy

    一般来讲,java中,对象的copy一般是通过Beans.copy(B, A);用来将A对象复制给B对象,包括对象里面的属性和值. 但但但...... 这样做,有一个很严重的问题,那就是:如果把A对象 ...

  4. Spark学习之路 (二十七)图简介

    一.图 1.1 基本概念 图是由顶点集合(vertex)及顶点间的关系集合(边edge)组成的一种数据结构. 这里的图并非指代数中的图.图可以对事物以及事物之间的关系建模,图可以用来表示自然发生的连接 ...

  5. (Review cs231n)loss function and optimization

    分类器需要在识别物体变化时候具有很好的鲁棒性(robus) 线性分类器(linear classifier)理解为模板的匹配,根据数量,表达能力不足,泛化性低:理解为将图片看做在高维度区域 线性分类器 ...

  6. android使用ARouter跳转activity(阿里巴巴开源的)

    android使用ARouter跳转activity(阿里巴巴开源的) 使用ARouter方式,点击按钮跳转到其他activitypublic void buyOrSell(String str){ ...

  7. maven 项目打可执行jar包

    昨晚,突然就来了紧急任务. 验签较慢,着手优化,发来一个demo.     首先需要把该demo部署在Linux上.     该项目是maven 项目,所以用maven打个jar包,打完jar包之后, ...

  8. AtCoder Beginner Contest 083 (AB)

    A - Libra 题目链接:https://abc083.contest.atcoder.jp/tasks/abc083_a Time limit : 2sec / Memory limit : 2 ...

  9. [转载]PowerDesigner生成的ORACLE 建表脚本中去掉对象的双引号,设置大、小写

    若要将 CDM 中将 Entity的标识符都设为指定的大小写,则可以这么设定: 打开cdm的情况下,进入Tools-Model Options-Naming Convention,把Name和Code ...

  10. 每日linux命令学习-grep模式检索

    grep模式检索指令包括grep,egrep,和fgrep,.Linux系统使用正则表达式优化文本检索,所以在此,笔者首先学习了一下正则表达式. 1. 正则表达式 正则表达式使用被称为元字符(Meta ...