题目大意不多说了

貌似每个苦逼的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. jQuery attr() 源码解读

    我们知道,$().attr()实质上是内部调用了jQuery.access方法,在调用时jQuery.attr作为回调传入.在通过种种判断(参看jQuery.access()方法)之后,取值和赋值最后 ...

  2. asp.net 微信登录实现方式

    之前我以为做微信登录跟微信公众号有关,后来发现是我想多了.原来微信还有一个叫开放平台的东西,见下图: 我的这个已经生成好了,没有的需要创建一个,https://open.weixin.qq.com/c ...

  3. 类似QQ在线离线好友界面

    把头像设置成圆形的代码如下: package com.example.lesson6_11_id19; import android.content.Context; import android.c ...

  4. 找不到draw9patch.bat?已经不用找了

    Google 已经因为 draw9patch 热门的原因,把它集成在 Android Studio 里面了, 你现在可以直接在 Android Studio 里直接打开编辑了.

  5. Performance engineering introduction

    1.Performance Software performance is one of software quality attributes,  it  equal to efficiency w ...

  6. Knockout-了解Observable与computed

    KO是什么? KO不是万能的,它的出现主要是为了方便的解决下面的问题: UI元素较多,用户交互比较频繁,需要编写大量的手工代码维护UI元素的状态.样式等属性? UI元素之间关系比较紧密,比如操作一个元 ...

  7. centos启用socks5服务

    直接在终端用 root 安装 *** 官方客户端 apt-get install python-pip -ypip install shadowsocks 然后编辑 /etc/shadowsocks. ...

  8. jmeter+ant+jenkins

    前提:需要先配置下面两个环境,严格按照本人的配置去配,要不然后面你会看不懂 (1)ant+jmeter集成:http://blog.csdn.net/qq_23101033/article/detai ...

  9. Windows API函数大全(完整)

    Windows API函数大全,从事软件开发的朋友可以参考下 1. API之网络函数 WNetAddConnection 创建同一个网络资源的永久性连接 WNetAddConnection2 创建同一 ...

  10. docker 镜像仓库的安装与使用

    安装Docker Compose 解决依赖 [root@service-1 ~]# curl -L "https://github.com/docker/compose/releases/d ...