BZOJ 1500 [NOI2005]维修数列 FHQ Treap
终于A了这题。。。这题还是很好。。。但是我太菜。。。重构了三遍qwq
FHQ Treap大法好!qwq。。。~~
Ins:直接拿输入造一棵树,把原来的树split成[1,pos],[pos+1,n],然后merge三棵树;
Del:把要删的区间split出来,merge他两边的树,记着要回收内存;
Mk-Same:把要改的区间split出来,打上标记,更新这棵树根的信息(见cover(x,v)),再merge回去;
Rev:把要翻转的区间split出来,打上标记,更新这棵树根的信息(见reverse(x)),再merge回去;
Get:把要求的区间split出来,输出sum[根],然后再merge回去;
Mx:输出mx[根]
维护最大子段和的思路跟线段树是类似的(链接)
顺便说一下自己当初犯的错误:
1.没有及时下放rev标记;重构x1
2.由于读取字符串用的getchar(),但是操作中有些串有负号。。。导致我读进来一堆负数。。。以后乖乖用字符串吧。。;重构x2,第三次重构才发现
3.stk内存池开小了。。。以为自己哪里递归写错了MLE+RE,后来看到网上有用queue的,就水了一波结果水过了。。后来又换成了数组stk。。;重构x3
代码:
#include<cstdio>
#include<iostream>
#include<queue>
#include<cstdlib>
#define R register int
#define ls(x) (ch[x][0])
#define rs(x) (ch[x][1])
using namespace std;
const int N=,Inf=;
inline int g() {
R ret=,fix=; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-:fix;
do ret=ret*+(ch^); while(isdigit(ch=getchar())); return ret*fix;
}
int n,m,tot,rt,top,sz[N],ch[N][],vl[N],mxl[N],mxr[N],mx[N],sum[N],tg[N],cov[N],dat[N],a[N>>],stk[N<<];
inline int max(int a,int b) {return a>b?a:b;}
inline int cre(int v) {R x; if(top) x=stk[top],--top; else x=++tot;
sz[x]=,ls(x)=rs(x)=tg[x]=; cov[x]=Inf,dat[x]=rand();
vl[x]=sum[x]=mx[x]=mxl[x]=mxr[x]=v; return x;
}
inline void upd(int x) {
if(!x) return ; sz[x]=sz[ls(x)]+sz[rs(x)]+; sum[x]=sum[ls(x)]+sum[rs(x)]+vl[x];
mx[x]=max(max(mxl[rs(x)],)+vl[x]+max(mxr[ls(x)],),max(mx[ls(x)],mx[rs(x)]));
mxl[x]=max(mxl[ls(x)],sum[ls(x)]+vl[x]+max(mxl[rs(x)],));
mxr[x]=max(mxr[rs(x)],sum[rs(x)]+vl[x]+max(mxr[ls(x)],));
}
inline void cover(int x,int v) {vl[x]=cov[x]=v,sum[x]=sz[x]*v,mxl[x]=mxr[x]=max(sum[x],),mx[x]=max(vl[x],sum[x]);}
inline void reverse(int x) {swap(ls(x),rs(x)),swap(mxl[x],mxr[x]),tg[x]^=;}
inline void spread(int x) {
if(tg[x]) {if(ls(x)) reverse(ls(x)); if(rs(x)) reverse(rs(x));}
if(cov[x]!=Inf) {if(ls(x)) cover(ls(x),cov[x]); if(rs(x)) cover(rs(x),cov[x]);} tg[x]=,cov[x]=Inf;
}
inline int build(int l,int r) {
if(l>r) return ; R md=l+r>>,v=a[md]; R x=cre(v);
ls(x)=build(l,md-),rs(x)=build(md+,r); upd(x); return x;
}
inline void split(int o,int rk,int& x,int& y) {
if(!o) {x=y=; return ;} spread(o);
if(rk>sz[ls(o)]) x=o,split(rs(x),rk-sz[ls(x)]-,rs(x),y);
else y=o,split(ls(y),rk,x,ls(y)); upd(o);
}
inline int merge(int x,int y) {
if(!x||!y) return x|y; spread(x),spread(y);
if(dat[x]<dat[y]) {rs(x)=merge(rs(x),y); upd(x); return x;}
else {ls(y)=merge(x,ls(y)); upd(y); return y;}
}
inline void del(int x) {if(!x) return; del(ls(x)),stk[++top]=x,del(rs(x));}
signed main() { R w,x,y,z; srand(); vl[]=mx[]=-Inf,sum[]=sz[]=tg[]=cov[]=;
n=g(),m=g(); for(R i=,x;i<=n;++i) a[i]=g(); rt=build(,n); while(m--) { register char ch;
while(!isalpha(ch=getchar())); if(ch=='M') {
getchar(),ch=getchar(); if(ch=='K') {
while(!isspace(ch=getchar())); R pos=g(),tot=g(),c=g(); split(rt,pos-,x,y),split(y,tot,y,z);
cover(y,c); rt=merge(x,merge(y,z));
} else if(ch=='X') {printf("%d\n",mx[rt]); while(!isspace(ch=getchar()));}
} else if(ch=='I') {R pos=g(),tot=g(); for(R i=,x;i<=tot;++i) a[i]=g(); z=build(,tot);split(rt,pos,x,y),rt=merge(merge(x,z),y);}
else if(ch=='D') {while(!isspace(ch=getchar())); R pos=g(),tot=g(); split(rt,pos-,x,y),split(y,tot,y,z),rt=merge(x,z); del(y);}
else if(ch=='R') {while(!isspace(ch=getchar())); R pos=g(),tot=g(); split(rt,pos-,x,y),split(y,tot,y,z); reverse(y); rt=merge(x,merge(y,z));}
else if(ch=='G') {while(!isspace(ch=getchar())); R pos=g(),tot=g(); split(rt,pos-,x,y),split(y,tot,y,z); printf("%d\n",sum[y]); rt=merge(x,merge(y,z));}
}
}
2019.05.11
BZOJ 1500 [NOI2005]维修数列 FHQ Treap的更多相关文章
- 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]维修数列
[算法]splay [题解]数据结构 感谢Occult的模板>_<:HYSBZ 1500 维修数列 #include<cstdio> #include<cctype> ...
- 1500: [NOI2005]维修数列
Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目.第2行包含N个数字,描述初始时的数列.以下M行,每行一 ...
- 【BZOJ】1500: [NOI2005]维修数列(splay+变态题)
http://www.lydsy.com/JudgeOnline/problem.php?id=1500 模板不打熟你确定考场上调试得出来? 首先有非常多的坑点...我遇到的第一个就是,如何pushu ...
- 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]维修数列 有一段时间没写博客了,最近在刚数据结构......各种板子背得简直要起飞,题目也是一大堆做不完,这里就挑一道平衡树的题来写写好了 ...
随机推荐
- bzoj1000~1025
以后还是这样 25道题一起发 看着爽 noip失利之后发粪涂墙 刷了一波bzoj 题解: bzoj1000 A+B问题 这题不同的人有不同的写法,我写了个线段树套Treap,应该还是挺简单的 但是看别 ...
- POJ1112 Team Them Up!
Team them up! Input file teams.in Output file teams.out Your task is to divide a number of persons i ...
- CH#24C 逃不掉的路 和 HDU3686 Traffic Real Time Query System
逃不掉的路 CH Round #24 - 三体杯 Round #1 题目描述 现代社会,路是必不可少的.任意两个城镇都有路相连,而且往往不止一条.但有些路连年被各种XXOO,走着很不爽.按理说条条大路 ...
- P1030 求先序排列
题目描述 给出一棵二叉树的中序与后序排列.求出它的先序排列.(约定树结点用不同的大写字母表示,长度<=8). 输入输出格式 输入格式: 2行,均为大写字母组成的字符串,表示一棵二叉树的中序与后序 ...
- 恢复到特定点(时间点、scn、日志序列号),rman不完全恢复
将数据库.表空间.数据文件等恢复至恢复备份集保存时间中的任何一个时间点/SCN/日志序列(一般是日志挖掘找到误操作点),但须谨慎,操作前一定需要做好备份,具备条件的情况下最好先恢复到异机,避免业务停机 ...
- bzoj 4815 小Q的表格 —— 反演+分块
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4815 思路就和这里一样:https://blog.csdn.net/leolyun/arti ...
- xshell 登录虚拟机ubuntu
本地装的Ubuntu虚拟机. 宿主机是win10, 互相之间能ping通,就是Xshell连不上,而且也不能弹出用户名和密码框. 后来解决,具体过程如下: 1: ifconfig -a命令得到 ...
- 外置式与增量式PID模板程序(51单片机c语言)
外置式PID模板 #define MuBiaoCS 0 //目标常数 #define CHang_aCS 0 //比例常数 #define CHang_bCS 0 //积分常数 #define CHa ...
- javascript之模拟块级作用域
在java.C++等语言中,变量i在会在for循环的语句块中定义,循环一旦结束,变量i就会被销毁.可是在javaScript中,从定义开始,就可以在函数内部随处访问.比如 function outpu ...
- 16_点击事件第三种写法_activity实现接口
第一种写法是有名内部类,第二种写法是匿名内部类,第三种写法是MainActivity实现接口OnClickListener.直接让MainActivity实现了OnClickListener这个接口. ...