splay模板三合一 luogu2042 [NOI2005]维护数列/bzoj1500 [NOI2005]维修数列 | poj3580 SuperMemo | luogu3391 【模板】文艺平衡树(Splay)
先是维修数列
题解看这里,但是我写的跑得很慢
#include <iostream>
#include <cstdio>
using namespace std;
int n, m, idx[500005], a[500005], rot=0, uu, vv, sta[500005], din, ww, cnt;
const int oo=0x3f3f3f3f;
char ss[25];
struct Splay{
int zdz[500005], sum[500005], lma[500005], rma[500005], siz[500005], val[500005];
int s[500005][2], fa[500005];
bool tag[500005], rev[500005];
void clr(int x){
zdz[x] = sum[x] = lma[x] = rma[x] = siz[x] = val[x] = s[x][0] = s[x][1] = fa[x] = 0;
tag[x] = rev[x] = 0;
}
int gx(int x){
return s[fa[x]][1]==x;
}
void recycle(int x){
if(s[x][0]) recycle(s[x][0]);
if(s[x][1]) recycle(s[x][1]);
sta[++din] = x;
clr(x);
}
void upd(int x){
int l=s[x][0], r=s[x][1];
sum[x] = sum[l] + sum[r] + val[x];
siz[x] = siz[l] + siz[r] + 1;
zdz[x] = max(max(zdz[l], zdz[r]), lma[r]+val[x]+rma[l]);
lma[x] = max(lma[l], sum[l]+val[x]+lma[r]);
rma[x] = max(rma[r], sum[r]+val[x]+rma[l]);
}
void build(int l, int r, int f){
int mid=(l+r)>>1, now=idx[mid], pre=idx[f];
if(l==r){
clr(now);
zdz[now] = sum[now] = a[l];
lma[now] = rma[now] = max(a[l], 0);
siz[now] = 1;
}
if(l<mid) build(l, mid-1, mid);
if(mid<r) build(mid+1, r, mid);
val[now] = a[mid]; fa[now] = pre;
upd(now);
s[pre][mid>=f] = now;
}
void pushDown(int x){
int l=s[x][0], r=s[x][1];
if(tag[x]){
tag[x] = rev[x] = 0;
if(l) tag[l] = 1, val[l] = val[x], sum[l] = siz[l] * val[x];
if(r) tag[r] = 1, val[r] = val[x], sum[r] = siz[r] * val[x];
if(val[x]>=0){
if(l) lma[l] = rma[l] = zdz[l] = sum[l];
if(r) lma[r] = rma[r] = zdz[r] = sum[r];
}
else{
if(l) lma[l] = rma[l] = 0, zdz[l] = val[x];
if(r) lma[r] = rma[r] = 0, zdz[r] = val[x];
}
}
if(rev[x]){
rev[x] = false; rev[l] ^= 1; rev[r] ^= 1;
swap(lma[l], rma[l]); swap(lma[r], rma[r]);
swap(s[l][0], s[l][1]); swap(s[r][0], s[r][1]);
}
}
int queryLoc(int x, int w){
pushDown(x);
if(w<=siz[s[x][0]]) return queryLoc(s[x][0], w);
else if(w>siz[s[x][0]]+1) return queryLoc(s[x][1], w-siz[s[x][0]]-1);
else return x;
}
void xf(int x){
if(fa[x]) xf(fa[x]);
pushDown(x);
}
void rotate(int x){
int old=fa[x], oldf=fa[old], w=gx(x);
s[old][w] = s[x][w^1]; s[x][w^1] = old;
fa[s[old][w]] = old; fa[old] = x; fa[x] = oldf;
if(oldf) s[oldf][s[oldf][1]==old] = x;
else rot = x;
upd(old); upd(x);
}
void splay(int x, int goal){
xf(x);
while(fa[x]!=goal){
int f=fa[x];
if(fa[f]!=goal) rotate(gx(f)==gx(x)?f:x);
rotate(x);
}
upd(x);
}
void insert(int uu, int vv){
for(int i=1; i<=vv; i++){
scanf("%d", &a[i]);
if(din) idx[i] = sta[din--];
else idx[i] = ++cnt;
}
build(1, vv, 0);
int ww=idx[(vv+1)>>1];
int tx=queryLoc(rot, uu+1), ty=queryLoc(rot, uu+2);
splay(tx, 0); splay(ty, rot);
s[ty][0] = ww; fa[ww] = ty;
upd(ty); upd(tx);
}
int spilt(int uu, int vv){
int tx=queryLoc(rot, uu), ty=queryLoc(rot, uu+vv+1);
splay(tx, 0); splay(ty, rot);
return s[ty][0];
}
void shanssu(int uu, int vv){
int x=spilt(uu, vv), y=fa[x];
recycle(x); s[y][0] = 0;
upd(y); upd(fa[y]);
}
void modify(int uu, int vv, int ww){
int x=spilt(uu, vv), f=fa[x];
val[x] = ww; tag[x] = true; sum[x] = siz[x] * ww;
if(ww>=0) lma[x] = rma[x] = zdz[x] = sum[x];
else lma[x] = rma[x] = 0, zdz[x] = ww;
upd(f); upd(fa[f]);
}
void reverse(int uu, int vv){
int x=spilt(uu, vv), f=fa[x];
if(!tag[x]){
rev[x] ^= 1;
swap(s[x][0], s[x][1]);
swap(lma[x], rma[x]);
upd(f); upd(fa[f]);
}
}
int getSum(int uu, int vv){
int x=spilt(uu, vv);
return sum[x];
}
}splay;
int main(){
cin>>n>>m;
splay.zdz[0] = a[1] = a[n+2] = -oo;
for(int i=1; i<=n; i++) scanf("%d", &a[i+1]);
for(int i=1; i<=n+2; i++) idx[i] = i;
splay.build(1, n+2, 0);
rot = (n + 3) >> 1;
cnt = n + 2;
while(m--){
scanf("%s", ss);
if(ss[0]=='I'){
scanf("%d %d", &uu, &vv);
splay.insert(uu, vv);
}
if(ss[0]=='D'){
scanf("%d %d", &uu, &vv);
splay.shanssu(uu, vv);
}
if(ss[0]=='M' && ss[2]=='K'){
scanf("%d %d %d", &uu, &vv, &ww);
splay.modify(uu, vv, ww);
}
if(ss[0]=='R'){
scanf("%d %d", &uu, &vv);
splay.reverse(uu, vv);
}
if(ss[0]=='G'){
scanf("%d %d", &uu, &vv);
printf("%d\n", splay.getSum(uu, vv));
}
if(ss[0]=='M' && ss[2]=='X')
printf("%d\n", splay.zdz[rot]);
}
return 0;
}
下面是poj的,稍加改动即可ac洛谷。
如果想看题意分析及讲解请看这里,讲得很好,一下就让我明白splay维护区间了。
splay的价值在于维护区间,如果只是维护点的话完全可以用treap等平衡树代替
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int n, m, uu, vv, ww, rot, sze;
const int oo=0x3f3f3f3f;
char ss[15];
struct Splay{
int s[200005][2], zxz[200005], val[200005], fa[200005], siz[200005];
int rev[200005], tag[200005];
void clr(int x){
s[x][0] = s[x][1] = zxz[x] = val[x] = fa[x] = siz[x] = rev[x] = tag[x] = 0;
}
int gx(int x){
return s[fa[x]][1]==x;
}
int newNode(int x){
clr(++sze); siz[sze] = 1;
val[sze] = zxz[sze] = x; return sze;
}
void ins(int x){
newNode(x); s[rot][1] = sze; fa[sze] = rot; splay(sze, 0);
}
int queryLoc(int now, int x){
pushDown(now);
if(x<=siz[s[now][0]]) return queryLoc(s[now][0], x);
else if(x>siz[s[now][0]]+1) return queryLoc(s[now][1], x-siz[s[now][0]]-1);
else return now;
}
void upd(int x){
siz[x] = siz[s[x][0]] + siz[s[x][1]] + 1;
zxz[x] = val[x];
if(s[x][0]) zxz[x] = min(zxz[x], zxz[s[x][0]]);
if(s[x][1]) zxz[x] = min(zxz[x], zxz[s[x][1]]);
}
void rotate(int x){
int old=fa[x], oldf=fa[old], w=gx(x);
s[old][w] = s[x][w^1]; s[x][w^1] = old;
fa[s[old][w]] = old; fa[old] = x; fa[x] = oldf;
if(oldf) s[oldf][s[oldf][1]==old] = x;
else rot = x;
upd(old); upd(x);
}
void pushDown(int x){
if(tag[x])
for(int i=0; i<2; i++)
if(s[x][i]){
zxz[s[x][i]] += tag[x];
val[s[x][i]] += tag[x];
tag[s[x][i]] += tag[x];
}
if(rev[x]){
if(s[x][0]) rev[s[x][0]] ^= 1;
if(s[x][1]) rev[s[x][1]] ^= 1;
swap(s[x][0], s[x][1]);
}
tag[x] = rev[x] = 0;
}
void xf(int x){
if(fa[x]) xf(fa[x]);
pushDown(x);
}
void splay(int x, int goal){
xf(x);
while(fa[x]!=goal){
int f=fa[x];
if(fa[f]!=goal) rotate(gx(x)==gx(f)?f:x);
rotate(x);
}
upd(x);
}
void update(int uu, int vv, int ww){
int tx=queryLoc(rot, uu), ty=queryLoc(rot, vv+2);
splay(tx, 0); splay(ty, rot);
val[s[ty][0]] += ww; zxz[s[ty][0]] += ww; tag[s[ty][0]] += ww;
}
void reverse(int uu, int vv){
int tx=queryLoc(rot, uu), ty=queryLoc(rot, vv+2);
splay(tx, 0); splay(ty, rot);
rev[s[ty][0]] ^= 1;
}
void revolve(int uu, int vv, int ww){
int len=vv-uu+1;
ww = (ww%len+len)%len;
int tx=queryLoc(rot, vv-ww+1), ty=queryLoc(rot, vv+2);
int x=queryLoc(rot, uu), y=queryLoc(rot, uu+1);
splay(tx, 0); splay(ty, rot);
int tmp=s[ty][0]; s[ty][0] = 0;
splay(x, 0); splay(y, rot);
s[y][0] = tmp; fa[s[y][0]] = y;
}
void insert(int uu, int vv){
int tx=queryLoc(rot, uu+1), ty=queryLoc(rot, uu+2);
splay(tx, 0); splay(ty, rot);
s[ty][0] = newNode(vv); fa[s[ty][0]] = ty;
}
void shanchu(int uu){
int tx=queryLoc(rot, uu), ty=queryLoc(rot, uu+2);
splay(tx, 0); splay(ty, rot);
s[ty][0] = 0;
}
int queryMin(int uu, int vv){
int tx=queryLoc(rot, uu), ty=queryLoc(rot, vv+2);
splay(tx, 0); splay(ty, rot);
return zxz[s[ty][0]];
}
}splay;
int main(){
cin>>n;
rot = splay.newNode(oo);
for(int i=1; i<=n; i++){
scanf("%d", &uu);
splay.ins(uu);
}
splay.ins(oo);
cin>>m;
while(m--){
scanf("%s", ss);
if(ss[0]=='A'){
scanf("%d %d %d", &uu, &vv, &ww);
splay.update(uu, vv, ww);
}
if(ss[0]=='R' && ss[3]=='E'){
scanf("%d %d", &uu, &vv);
splay.reverse(uu, vv);
}
if(ss[0]=='R' && ss[3]=='O'){
scanf("%d %d %d", &uu, &vv, &ww);
splay.revolve(uu, vv, ww);
}
if(ss[0]=='I'){
scanf("%d %d", &uu, &vv);
splay.insert(uu, vv);
}
if(ss[0]=='D'){
scanf("%d", &uu);
splay.shanchu(uu);
}
if(ss[0]=='M'){
scanf("%d %d", &uu, &vv);
printf("%d\n", splay.queryMin(uu, vv));
}
}
return 0;
}
splay模板三合一 luogu2042 [NOI2005]维护数列/bzoj1500 [NOI2005]维修数列 | poj3580 SuperMemo | luogu3391 【模板】文艺平衡树(Splay)的更多相关文章
- luoguP3391[模板]文艺平衡树(Splay) 题解
链接一下题目:luoguP3391[模板]文艺平衡树(Splay) 平衡树解析 这里的Splay维护的显然不再是权值排序 现在按照的是序列中的编号排序(不过在这道题目里面就是权值诶...) 那么,继续 ...
- 【阶梯报告】洛谷P3391【模板】文艺平衡树 splay
[阶梯报告]洛谷P3391[模板]文艺平衡树 splay 题目链接在这里[链接](https://www.luogu.org/problemnew/show/P3391)最近在学习splay,终于做对 ...
- 【BZOJ-1500】维修数列 Splay
1500: [NOI2005]维修数列 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 11047 Solved: 3460[Submit][Statu ...
- BZOJ 3223: Tyvj 1729 文艺平衡树-Splay树(区间翻转)模板题
3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 6881 Solved: 4213[Submit][Sta ...
- [洛谷P3391] 文艺平衡树 (Splay模板)
初识splay 学splay有一段时间了,一直没写...... 本题是splay模板题,维护一个1~n的序列,支持区间翻转(比如1 2 3 4 5 6变成1 2 3 6 5 4),最后输出结果序列. ...
- BZOJ3223 文艺平衡树(splay)
题目背景 这是一道经典的Splay模板题——文艺平衡树. 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1, ...
- BZOJ3223: Tyvj 1729 文艺平衡树 [splay]
3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 3595 Solved: 2029[Submit][Sta ...
- Tyvj P1729 文艺平衡树 Splay
题目: http://tyvj.cn/p/1729 P1729 文艺平衡树 时间: 1000ms / 空间: 131072KiB / Java类名: Main 背景 此为平衡树系列第二道:文艺平衡树 ...
- BZOJ 3223: Tyvj 1729 文艺平衡树(splay)
速度居然进前十了...第八... splay, 区间翻转,用一个类似线段树的lazy标记表示是否翻转 ------------------------------------------------- ...
随机推荐
- Get和Post的初步探究
Get请求和Post请求这两种基本请求类型,大部分开发者心里大概都有所谓的"标准答案",但博主最近用Postman测试接口的时候,遇到传参的问题:用post请求,参数放在reque ...
- Mind must be master of the body, strong mind can separate the body from its suffering.
Mind must be master of the body, strong mind can separate the body from its suffering.意志是身体的主人,有顽强的意 ...
- Java 继承与重写
1.类的继承 1)继承 父类:所有子类所共有的属性和行为 子类:子类所特有的属性和行为 通过extends关键字来实现类的继承 子类(Sub class)可以继承父类(Super class)的成员变 ...
- [dp]uestc oj E - 菲波拉契数制
E - 菲波拉契数制 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Submi ...
- Python-OpenCV——Image Blurring(Image Smoothing)
通过将图像与低通滤波器内核卷积来实现图像模糊.它有助于消除噪音.它实际上从图像中去除了高频内容(例如:噪声,边缘).因此在此操作中边缘会有点模(嗯,有模糊技术,也不会模糊边缘). OpenCV主要提供 ...
- Logistic回归,梯度上升算法理论详解和实现
经过对Logistic回归理论的学习,推导出取对数后的似然函数为 现在我们的目的是求一个向量,使得最大.其中 对这个似然函数求偏导后得到 根据梯度上升算法有 进一步得到 我们可以初始化向量为0,或者随 ...
- oracle中print_table存储过程实例介绍
oracle中pro_print_table存储过程实例介绍 存储过程(Stored Procedure),就是一组用于完成特定数据库功能的SQL语句集,该SQL语句集经过编译后存储在数据库系统中.这 ...
- 1_HDFS理论及安装部署
一.hadoop简介 1.hadoop的初衷是为了解决Nutch的海量数据爬取和存储的需要,HDFS来源于google的GFS,MapReduce来源于Google的MapReduce,HBase来源 ...
- cocos2dx for lua 摄像机移动
在cocos2dx中,我们想通过移动摄像机来做一些特殊处理,比如将摄像机聚焦在某个物体上,或者摄像机颤抖,摄像机原理观察sprite回收状况等等, 都需要通过相机移动来使用. cocos2dx中的摄像 ...
- jq封装插件,简单dome
(function($) { $.fn.extend({ bold: function() { this.css({ fontWeight: "bold", color: 'red ...