题目大意不多说了

貌似每个苦逼的acmer都要做一下这个splay树的模版题目吧

还是有很多操作的,估计够以后当模版了。。。。

 #include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath> using namespace std;
const int N = ;
const int INF = 0x3f3f3f3f;
#define ls ch[x][0]
#define rs ch[x][1] struct SplayTree{
int ch[N][] , pre[N];
int ml[N] , mr[N] , mm[N]; //区间最大
int val[N] , sz[N] , sum[N] , size , rt;
int rev[N] , to[N]; // lazy标记
int del[N] , top; //内部保存删除的数的位置,然后可以从其中提取位置给新进入的元素
int a[N]; void push_up(int x)
{
sz[x] = sz[ls]+sz[rs]+;
sum[x] = sum[ls]+sum[rs]+val[x];
/*********************/
ml[x] = max(ml[ls] , sum[ls]+val[x]+max(ml[rs] , ));
mr[x] = max(mr[rs] , sum[rs]+val[x]+max(mr[ls] , ));
mm[x] = max(mm[ls] , max(mm[rs] , max(ml[rs],)+max(mr[ls],)+val[x]));
/*********************/
} void push_down(int x)
{
if(rev[x]){
if(ls){
rev[ls]^= ;
swap(ml[ls] , mr[ls]);
}
if(rs){
rev[rs]^= ;
swap(ml[rs] , mr[rs]);
}
swap(ls , rs);
rev[x] = ;
}
/**to[x]的初始化要注意**/
if(to[x]!=-INF){
if(ls){
sum[ls] = sz[ls]*to[x];
ml[ls] = mr[ls] = mm[ls] = max(sum[ls] , to[x]);
val[ls] = to[ls] = to[x];
}
if(rs){
sum[rs] = sz[rs]*to[x];
ml[rs] = mr[rs] = mm[rs] = max(sum[rs] , to[x]);
val[rs] = to[rs] = to[x];
}
to[x] = -INF;
}
} void newNode(int &x , int fa , int v)
{
if(top != -)
x = del[top--];
else x = ++size;
ch[x][] = ch[x][] = ;
pre[x] = fa;
val[x] = v , sz[x] = ;
sum[x] = ml[x] = mr[x] = mm[x] = val[x];
rev[x] = , to[x] = -INF;
} void build(int &x , int l , int r , int fa)
{
if(l>r) return;
int m=(l+r)>>;
newNode(x , fa , a[m]);
build(ls , l , m- , x);
build(rs , m+ , r , x);
push_up(x);
} void init(int n)
{
/*****因为所有点的最终叶子节点都下标设为了0,所以0上的数据要不影响整棵树*****/
sz[] = sum[] = ch[][] = ch[][] = val[] = pre[] = ;
to[] = ml[] = mr[] = mm[] = -INF;
rev[] = ;
top = - , rt = size = ;
newNode(rt , , -INF);
newNode(ch[rt][] , rt , -INF);
build(ch[ch[rt][]][] , , n , ch[rt][]);
push_up(ch[rt][]);
push_up(rt);
} void Rotate(int x , int f)
{
int y=pre[x] , z=pre[y];
/**y要旋转到下方,下传lazy标记**/
push_down(y);
ch[y][!f] = ch[x][f] , pre[ch[x][f]] = y;
ch[x][f] = y , pre[y] = x;
ch[z][ch[z][]==y] = x , pre[x]=z;
push_up(y);
push_up(x);
} void Splay(int x , int goal)
{
while(pre[x] != goal){
if(pre[pre[x]] == goal) Rotate(x , ch[pre[x]][]==x);
else{
int y = pre[x] , z = pre[y];
int f = ch[z][] == y;
if(ch[y][f] == x) Rotate(x , !f);
else Rotate(y,f);
Rotate(x , f);
}
}
push_up(x);
if(goal == ) rt = x;
} int Select(int pos)
{
int x = rt;
push_down(x);
while(sz[ls]+ != pos){
if(sz[ls]+>pos) x=ls;
else{
pos = pos-sz[ls]-;
x = rs;
}
push_down(x);
}
return x;
}
/***从pos位置之后插入cnt个值***/
void Insert(int pos , int cnt)
{
int x = Select(pos);
Splay(x , );
int y = Select(pos+);
Splay(y , x);
build(ch[y][] , , cnt , y);
/***这里build将a[1~cnt]插入到splay树中,要push_up更新***/
push_up(y);
push_up(x);
}
/***回收被删除的数的位置***/
void Recycle(int x)
{
if(x){
del[++top]=x;
Recycle(ls);
Recycle(rs);
}
} void Delete(int s , int t)
{
int x = Select(s-) , y = Select(t+);
Splay(x , ) , Splay(y , x);
Recycle(ch[y][]);
ch[y][] = ;
/***这里y的左子树删除,明显子树数据改变,所以要重新push_up更新数据***/
push_up(y);
push_up(x);
}
/****将s~t区间内的所有值都修改为v****/
void update(int s , int t , int v)
{
int x = Select(s-) , y = Select(t+);
Splay(x , ) , Splay(y , x);
int ptr = ch[y][];
to[ptr]=v;
val[ptr]=v;
sum[ptr]=v*sz[ptr];
ml[ptr] = mr[ptr] = mm[ptr] = max(sum[ptr] , v);
return ;
} void Reverse(int s , int t)
{
int x = Select(s-) , y = Select(t+);
Splay(x , ) , Splay(y , x);
int ptr = ch[y][];
rev[ptr]^=;
swap(ml[ptr] , mr[ptr]);
} int querySum(int s , int t)
{
int x = Select(s-) , y = Select(t+);
// cout<<"x: "<<x<<" y: "<<y<<endl;
Splay(x , ) , Splay(y , x);
return sum[ch[y][]];
} int queryMax()
{
int x = Select() , y = Select(sz[rt]);
Splay(x , ) , Splay(y , x);
return mm[ch[y][]];
}
}spt;
int main()
{
// freopen("a.in" , "r" , stdin);
int n , m;
char str[] ;
int s , t , v , pos , k;
while(~scanf("%d%d" , &n , &m))
{
for(int i= ; i<=n ; i++) scanf("%d" , &spt.a[i]);
spt.init(n);
/*
for(int i=0 ; i<=spt.size ; i++){
cout<<"i: "<<i<<" sum: "<<spt.sum[i]<<" l: "<<spt.ch[i][0]<<" lv: "<<spt.val[spt.ch[i][0]]<<" r: "<<spt.ch[i][1]<<" rv: "<<spt.val[spt.ch[i][1]]<<endl;
}*/
for(int i= ; i<m ; i++){
scanf("%s" , str);
if(str[] == 'I'){
scanf("%d%d" , &pos , &k);
for(int i= ; i<=k ; i++) scanf("%d" , &spt.a[i]);
spt.Insert(pos+ , k);
}
else if(str[]=='D'){
scanf("%d%d" , &pos , &k);
spt.Delete(pos+ , pos+k);
}
else if(str[] == 'M' && str[] == 'K'){
scanf("%d%d%d" , &pos , &k , &v);
spt.update(pos+ , pos+k , v);
}
else if(str[] == 'R'){
scanf("%d%d" , &pos , &k);
spt.Reverse(pos+ , pos+k);
}
else if(str[] == 'G'){
scanf("%d%d" , &pos , &k);
printf("%d\n" , spt.querySum(pos+ , pos+k));
}
else{
/****这里不能直接用spt.mm[rt]作为答案,因为为了方便查询,
我们增加了两个不包含在本身数组的点,直接spt.mm[rt]会把这两个点也算进来***/
printf("%d\n" , spt.queryMax());
}
}
}
return ;
}

bzoj 1500 [NOI 2005] 维修数列的更多相关文章

  1. 洛谷 2042 BZOJ 1500 NOI 2005 维护数列

    [题意概述] 维护一个数列,要求支持以下6种操作: [题解] 大Boss...可以用Treap解决 需要用到垃圾回收.线性建树. #include<cstdio> #include< ...

  2. BZOJ 1500/Luogu 2042 - 维修数列 - [NOI2005][Splay]

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1500 题目链接:https://www.luogu.org/problemnew/sho ...

  3. NOI 2005 维修数列

    妈妈呀我终于过了!!!原来是数据坑我!!! 弃疗弃疗弃疗弃疗!!!!我调了一天呢....被GET_SUM 8 0打败了.... 啥也不说了....还是我太年轻.... 更新了一下常数,跑的还是可以的: ...

  4. NOI 2005维护数列

    题目描述 请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格) 输入输出格式 输入格式: 输入文件的第 1 行包含两个数 N 和 M, ...

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

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

  6. [BZOJ 1500] [NOI2005] 维修数列

    题目链接:BZOJ - 1500 题目分析 我要先说一下,这道题我写了一晚上,然后Debug了一整个白天..........再一次被自己的蒟蒻程度震惊= = 这道题是传说中的Splay维护数列的Bos ...

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

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

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

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

  9. 【BZOJ】1500: [NOI2005]维修数列

    [算法]splay [题解]数据结构 感谢Occult的模板>_<:HYSBZ 1500 维修数列 #include<cstdio> #include<cctype> ...

随机推荐

  1. 你不知道的border-radius

    对于border-radius这个属性,我们知道它可以用来设置边框圆角,利用它我们可以画出很多形状 这就需要了解到border-radius的各式写法: border-radius的写法: 1.只设置 ...

  2. PowerShell~语法与运算符

    基本语法 变量:$开头 $a = "Hello" 条件语句:if else ) { Write-Host "偶数" } else{ Write-Host &qu ...

  3. android开发学习 ------- MongoDB数据库简单理解

    首先说一下MongoDB是什么? MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的. MongoDB 是一个基于分布式文件存储的数据库. N ...

  4. AJPFX总结java开发常用类(包装,数字处理集合等)(二)

    二:进军集合类 集合其实就是存放对象的容器,专业点说就是集合是用来存储和管理其他对象的对象,即对象的容器.集合可以扩容,长度可变,可以存储多种类型的数据,而数组长度不可变,只能存储单一类型的元素 用一 ...

  5. java课程设计全程实录——第0天

    本次课设计划在5月25日完成.目前还剩18天. 第0天主要完成事项如下: 搭建开发环境 制定开发进度规划表 阅读前人的课设 详细: 1.IDE的下载,安装,以及配合使用的阿里巴巴编程规约插件的安装与测 ...

  6. CF778A(round 402 div.2 D) String Game

    题意: Little Nastya has a hobby, she likes to remove some letters from word, to obtain another word. B ...

  7. 列表、margin和padding的探讨、标签的分类

    一.列表 列表分为无序列表.有序列表和自定义列表 1.无序列表   <ul></ul> 1).内部必须有子标签,<li></li> 2).ul天生自带内 ...

  8. JS内置对象练习(慕课网题目)

    效果图: XXXX年XX月X日 星期X--班级总分为:81 格式要求: 1.显示打印的日期. 格式为类似“XXXX年XX月XX日 星期X” 的当前的时间. 2.计算出该班级的平均分(保留整数). 同学 ...

  9. Summary of 2016 International Trusted Computing and Cloud Security Summit

    1)      Welcome Remarks 2)      The advancement of Cloud Computing and Tursted Computing national st ...

  10. powerDesigner 把name项添加到注释(comment),完美方案!

    第一次写博客,分享一点经验吧,平时大家用powerDesigner的时候,pd是不会把name项默认添加到comment的,所以生成的数据库表里面也没有中文字段的注释. 我在网上查了一下.有解决方案了 ...