bzoj 1500 [NOI 2005] 维修数列
题目大意不多说了
貌似每个苦逼的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] 维修数列的更多相关文章
- 洛谷 2042 BZOJ 1500 NOI 2005 维护数列
[题意概述] 维护一个数列,要求支持以下6种操作: [题解] 大Boss...可以用Treap解决 需要用到垃圾回收.线性建树. #include<cstdio> #include< ...
- BZOJ 1500/Luogu 2042 - 维修数列 - [NOI2005][Splay]
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1500 题目链接:https://www.luogu.org/problemnew/sho ...
- NOI 2005 维修数列
妈妈呀我终于过了!!!原来是数据坑我!!! 弃疗弃疗弃疗弃疗!!!!我调了一天呢....被GET_SUM 8 0打败了.... 啥也不说了....还是我太年轻.... 更新了一下常数,跑的还是可以的: ...
- NOI 2005维护数列
题目描述 请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格) 输入输出格式 输入格式: 输入文件的第 1 行包含两个数 N 和 M, ...
- bzoj 1500: [NOI2005]维修数列 splay
1500: [NOI2005]维修数列 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 6556 Solved: 1963[Submit][Status ...
- [BZOJ 1500] [NOI2005] 维修数列
题目链接:BZOJ - 1500 题目分析 我要先说一下,这道题我写了一晚上,然后Debug了一整个白天..........再一次被自己的蒟蒻程度震惊= = 这道题是传说中的Splay维护数列的Bos ...
- [BZOJ 1500]维修数列 [Splay Tree从进阶到住院]
历尽艰辛终于A掉了这题QwQ 贴COGS评论区几句话=.= 策爷:"splay/块状链表的自虐题.".深刻理解到如果没有M倾向就不要去写这题了.. -Chenyao2333 记得b ...
- BZOJ 1500: [NOI2005]维修数列 (splay tree)
1500: [NOI2005]维修数列 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 4229 Solved: 1283[Submit][Status ...
- 【BZOJ】1500: [NOI2005]维修数列
[算法]splay [题解]数据结构 感谢Occult的模板>_<:HYSBZ 1500 维修数列 #include<cstdio> #include<cctype> ...
随机推荐
- RHEL 6.5----Nginx负载均衡
实验环境 主机名 IP master 192.168.30.130 node-1 192.168.30.131 node-2 192.168.30.132 在master上安装 本次安装过程统一采用Y ...
- aspx子集页面找父级页面元素
var Obj= window.parent.document.getElementById("ctl00_RightTopTree_hidJsonResult"); Obj.va ...
- Redis java操作客服端——jedis
1. Jedis 需要把jedis依赖的jar包添加到工程中.Maven工程中需要把jedis的坐标添加到依赖. 推荐添加到服务层.happygo-content-Service工程中. 1.1. 连 ...
- AJPFX总结I/O流操作(一)
在软件开发中,数据流和数据库操作占据了一个很重要的位置,所以,熟悉操作数据流和数据库,对于每一个开发者来说都是很重要的,今天就来总结一下I/O,数据库操作 一:从数据流开始 首先先有一个结构图看一下整 ...
- f# mathprovider
http://mathprovider.codeplex.com/ http://mathnetnumerics.codeplex.com/releases/view/110750 http://py ...
- 【学习笔记】OSG中相机参数的更改
#pragma comment(lib, "osg.lib") #pragma comment(lib, "osgDB.lib") #pragma commen ...
- Android性能分析工具Profile GPU rendering详细介绍
如何在一个应用中追踪和定位性能问题,甚至在没有它的源代码的情况下?? “Profile GPU rendering”(GPU渲染分析),一款Android4.1所引入的工具.你可以在“设置”应用的“开 ...
- 使用 Azure ARM 部署Word Press 遇到 Extension节点 扩展的问题
在使用Azure ARM模式部署wordpress,将php网站压缩成zip的形式在DefaultTemplate模板中已扩展的形式实现安装 遇到的问题总结: 1.开始在sites节点中,resour ...
- TensorFlow 安装 Win10 Python+GPU
前叙:有灵魂的程序都是每一个程序员的最终目标.TensorFlow了解下? 打算花几个月学机器学习,TensorFlow是很好的选择,折腾了会环境,略有心得分享下. 环境:win10 Python:3 ...
- vijos 1053 Easy sssp
描述 输入数据给出一个有N(2 <= N <= 1,000)个节点,M(M <= 100,000)条边的带权有向图. 要求你写一个程序, 判断这个有向图中是否存在负权回路. 如果从一 ...