【BZOJ】1500: [NOI2005]维修数列
【算法】splay
【题解】数据结构
感谢Occult的模板>_<:HYSBZ 1500 维修数列
#include<cstdio>
#include<cctype>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn=5e5+,inf=0x3f3f3f3f;
int n,m,root,a[maxn],t[maxn][],f[maxn],A[maxn],L[maxn],R[maxn],M[maxn],sum[maxn],en[maxn],g[maxn],s[maxn];
//关系类:f父亲 t儿子 | 数值类:num值 L左起最大子段和 R右起最大子段和 M最大子段和 sum和 s结点数 | 标记类:en覆盖标记 g翻转标记
queue<int>q;
int read()
{
char c;int s=,t=;
while(!isdigit(c=getchar()))if(c=='-')t=-;
do{s=s*+c-'';}while(isdigit(c=getchar()));
return s*t;
}
int Node(int fa,int num)
{
int sz=q.front();q.pop();
t[sz][]=t[sz][]=en[sz]=g[sz]=;
s[sz]=;f[sz]=fa;A[sz]=L[sz]=R[sz]=M[sz]=sum[sz]=num;
return sz;
}
void count(int x)//与线段树更新不同,记得加自身
{
L[x]=max(L[t[x][]],sum[t[x][]]+A[x]+max(,L[t[x][]]));
R[x]=max(R[t[x][]],sum[t[x][]]+A[x]+max(,R[t[x][]]));
M[x]=max(,R[t[x][]])+A[x]+max(,L[t[x][]]);
M[x]=max(M[x],max(M[t[x][]],M[t[x][]]));
sum[x]=sum[t[x][]]+A[x]+sum[t[x][]];
s[x]=s[t[x][]]++s[t[x][]];
}
void pushdown(int x)
{
if(g[x])
{
g[t[x][]]^=;g[t[x][]]^=;
swap(L[t[x][]],R[t[x][]]);
swap(L[t[x][]],R[t[x][]]);
swap(t[x][],t[x][]);
g[x]=;
}
if(en[x])
{
if(t[x][])
{
en[t[x][]]=;
A[t[x][]]=A[x];
sum[t[x][]]=A[x]*s[t[x][]];
L[t[x][]]=R[t[x][]]=M[t[x][]]=A[x]>?sum[t[x][]]:A[x];
}
if(t[x][])
{
en[t[x][]]=;
A[t[x][]]=A[x];
sum[t[x][]]=A[x]*s[t[x][]];
L[t[x][]]=R[t[x][]]=M[t[x][]]=A[x]>?sum[t[x][]]:A[x];
}
en[x]=;
}
}
void rotate(int x)
{
int k=x==t[f[x]][];
int y=f[x];
t[y][k]=t[x][!k];f[t[x][!k]]=y;
if(f[y])t[f[y]][y==t[f[y]][]]=x;f[x]=f[y];f[y]=x;
t[x][!k]=y;
L[x]=L[y];R[x]=R[y];M[x]=M[y];sum[x]=sum[y];s[x]=s[y];
count(y);
}
void splay(int x,int r)
{
for(int fa=f[r];f[x]!=fa;)//因为y被旋走了,所以要判断f[y]
{
if(f[f[x]]==fa){rotate(x);break;}
int X=x==t[f[x]][],Y=f[x]==t[f[f[x]]][];//等号别打少……
if(X^Y)rotate(x),rotate(x);
else rotate(f[x]),rotate(x);
}
}
void find(int &x,int k)
{
for(int i=x;i;)
{
pushdown(i);
if(k<=s[t[i][]]){i=t[i][];continue;}
if(k==s[t[i][]]+){splay(i,x);x=i;break;}
k-=s[t[i][]]+;i=t[i][];//else不安全。。。
}
}
void build(int fa,int &x,int l,int r)
{
if(l>r)return;
int mid=(l+r)>>;
x=Node(fa,a[mid]);
build(x,t[x][],l,mid-);
build(x,t[x][],mid+,r);
count(x);//
}
void insert()
{
int l=read(),k=read();
for(int i=;i<=k;i++)a[i]=read();
int r;build(,r,,k);
find(root,l+);find(t[root][],);
t[t[root][]][]=r;f[r]=t[root][];
count(t[root][]);count(root);//记得count
}
void erase(int x)
{
if(!x)return;
q.push(x);
erase(t[x][]);
erase(t[x][]);
}
void del()
{
int l=read(),k=read();
find(root,l);find(t[root][],k+);
erase(t[t[root][]][]);
t[t[root][]][]=;
count(t[root][]);count(root);//
}
void cover()
{
int l=read(),k=read(),num=read();
find(root,l);find(t[root][],k+);
int y=t[t[root][]][];
en[y]=;A[y]=num;
sum[y]=s[y]*A[y];
L[y]=R[y]=M[y]=A[y]>?sum[y]:A[y];
count(t[root][]);count(root);//
}
void round()
{
int l=read(),k=read();
find(root,l);find(t[root][],k+);
int y=t[t[root][]][];
g[y]^=;
swap(L[y],R[y]);
count(t[root][]);count(root);//
}
void getsum()
{
int l=read(),k=read();
find(root,l);find(t[root][],k+);
printf("%d\n",sum[t[t[root][]][]]);
}
void getM()
{
int sz=s[root];
find(root,);
find(t[root][],sz-);
printf("%d\n",M[t[t[root][]][]]);
}
char str[];
int main()
{
n=read();m=read();
a[]=a[n+]=root=;
for(int i=;i<=maxn;i++)q.push(i);
L[]=R[]=M[]=-inf;//使空结点干扰判断,过程中需保证任何时刻都不应修改到该点的值。
for(int i=;i<=n;i++)a[i]=read();
build(,root,,n+);
for(int i=;i<=m;i++)
{
scanf("%s",str);
if(str[]=='S')insert();
if(str[]=='L')del();
if(str[]=='K')cover();
if(str[]=='V')round();
if(str[]=='T')getsum();
if(str[]=='X')getM();
}
return ;
}
update:现在已改用fhq-treap代替splay。
【BZOJ】1500: [NOI2005]维修数列的更多相关文章
- bzoj 1500: [NOI2005]维修数列 splay
1500: [NOI2005]维修数列 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 6556 Solved: 1963[Submit][Status ...
- BZOJ 1500: [NOI2005]维修数列 (splay tree)
1500: [NOI2005]维修数列 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 4229 Solved: 1283[Submit][Status ...
- [BZOJ 1500] [NOI2005] 维修数列
题目链接:BZOJ - 1500 题目分析 我要先说一下,这道题我写了一晚上,然后Debug了一整个白天..........再一次被自己的蒟蒻程度震惊= = 这道题是传说中的Splay维护数列的Bos ...
- BZOJ 1500 [NOI2005]维修数列 FHQ Treap
终于A了这题...这题还是很好...但是我太菜...重构了三遍qwq FHQ Treap大法好!qwq...~~ Ins:直接拿输入造一棵树,把原来的树split成[1,pos],[pos+1,n], ...
- 【BZOJ】1500: [NOI2005]维修数列(splay+变态题)
http://www.lydsy.com/JudgeOnline/problem.php?id=1500 模板不打熟你确定考场上调试得出来? 首先有非常多的坑点...我遇到的第一个就是,如何pushu ...
- 1500: [NOI2005]维修数列
Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目.第2行包含N个数字,描述初始时的数列.以下M行,每行一 ...
- bzoj千题计划221:bzoj1500: [NOI2005]维修数列(fhq treap)
http://www.lydsy.com/JudgeOnline/problem.php?id=1500 1.覆盖标记用INF表示无覆盖标记,要求可能用0覆盖 2.代表空节点的0号节点和首尾的两个虚拟 ...
- [NOI2005] 维修数列
1500: [NOI2005]维修数列 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 8397 Solved: 2530 Description In ...
- [BZOJ1500][NOI2005]维修数列---解题报告
Portal Gun:[BZOJ1500][NOI2005]维修数列 有一段时间没写博客了,最近在刚数据结构......各种板子背得简直要起飞,题目也是一大堆做不完,这里就挑一道平衡树的题来写写好了 ...
随机推荐
- unity像素贪吃蛇
[ 星 辰 · 别 礼 ] 设计过程: 首先,在之前玩坏控制台做的那个c#贪吃蛇之后,我以为做unity会很简单,但事实比较不如人意...拖了好几天.因为过程中遇到一些问题 蛇身的移动,还是用列表,将 ...
- (十一)instanceof 和 getclass 的区别
判断两个对象是否为同一类型,时常用到getclass 和 instanceof ,而这两个函数又是时常让人混淆.下面从一个例子说明两者的区别: public class Test_drive { pu ...
- python学习第一天-语法学习
1.python简介 python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,Guido开始写能够解释Python语言语法的解释器.Python这个名字,来自 ...
- 3DMAX贴图无法显示
问题描述:我在点击"将材质指定给选定对象"按钮之后,模型只是变灰了,没有显示出我贴的图. 原因是:没有显示贴图. 我的解决方案:点击材质编辑器里面的"视口中显示敏感处理材 ...
- php添加扩展 在phpinfo能看到该扩展,但在cli用php -m 却看不到,为什么呢,求指教
1. 没有出现的原因是:执行时添加上php.ini的文件就可以了 $ /usr/local/php/bin/php -c /usr/local/php/etc/php.ini -m | grep ...
- hibernate.cfg.xml的详细解释
<!--标准的XML文件的起始行,version='1.0'表明XML的版本,encoding='gb2312'表明XML文件的编码方式--> < ...
- lucene 学习之编码篇
本文环境:lucene5.2 JDK1.7 IKAnalyzer 引入lucene相关包 <!-- lucene核心包 --> <dependency> <g ...
- 了解Solr
Solr 简 介 采用Java开发,基于Lucene的全文搜索服务器.同时对其进行了扩展,提供了比Lucene更为丰富的查询语言,同时实现了可配置.可扩展并对查询性能进行了优化,并且提供了一个完善的功 ...
- BZOJ 1202 狡猾的商人(带权并查集)
给出了l,r,w.我们就得知了s[r]-s[l-1]=w.也就是说,点l-1和点r的距离为w. 于是可以使用带权并查集,定义dis[i]表示点i到根节点的距离.查询和合并的时候维护一下就OK了. 如果 ...
- 【bzoj4491】我也不知道题目名字是什么 离线扫描线+线段树
题目描述 给定一个序列A[i],每次询问l,r,求[l,r]内最长子串,使得该子串为不上升子串或不下降子串 输入 第一行n,表示A数组有多少元素接下来一行为n个整数A[i]接下来一个整数Q,表示询问数 ...