先是维修数列

题解看这里,但是我写的跑得很慢

#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)的更多相关文章

  1. luoguP3391[模板]文艺平衡树(Splay) 题解

    链接一下题目:luoguP3391[模板]文艺平衡树(Splay) 平衡树解析 这里的Splay维护的显然不再是权值排序 现在按照的是序列中的编号排序(不过在这道题目里面就是权值诶...) 那么,继续 ...

  2. 【阶梯报告】洛谷P3391【模板】文艺平衡树 splay

    [阶梯报告]洛谷P3391[模板]文艺平衡树 splay 题目链接在这里[链接](https://www.luogu.org/problemnew/show/P3391)最近在学习splay,终于做对 ...

  3. 【BZOJ-1500】维修数列 Splay

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 11047  Solved: 3460[Submit][Statu ...

  4. BZOJ 3223: Tyvj 1729 文艺平衡树-Splay树(区间翻转)模板题

    3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 6881  Solved: 4213[Submit][Sta ...

  5. [洛谷P3391] 文艺平衡树 (Splay模板)

    初识splay 学splay有一段时间了,一直没写...... 本题是splay模板题,维护一个1~n的序列,支持区间翻转(比如1 2 3 4 5 6变成1 2 3 6 5 4),最后输出结果序列. ...

  6. BZOJ3223 文艺平衡树(splay)

    题目背景 这是一道经典的Splay模板题——文艺平衡树. 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1, ...

  7. BZOJ3223: Tyvj 1729 文艺平衡树 [splay]

    3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3595  Solved: 2029[Submit][Sta ...

  8. Tyvj P1729 文艺平衡树 Splay

    题目: http://tyvj.cn/p/1729 P1729 文艺平衡树 时间: 1000ms / 空间: 131072KiB / Java类名: Main 背景 此为平衡树系列第二道:文艺平衡树 ...

  9. BZOJ 3223: Tyvj 1729 文艺平衡树(splay)

    速度居然进前十了...第八... splay, 区间翻转,用一个类似线段树的lazy标记表示是否翻转 ------------------------------------------------- ...

随机推荐

  1. volley框架下发送和读取cookie

    首先volley本身不支持cookie,但是volley又非常好用(比如封装了网络请求的实现,内部支持并发, 不用我们再额外设计网络管理异步处理,网络请求不应在UI线程等等),那既想使用volley又 ...

  2. web APP到底和跨平台APP开发有什么区别?

    什么是web app? WebApp是指基于Web的系统和应用,其作用是向广大的最终用户发布一组复杂的内容和功能. 说的浅显易懂点儿就是因为移动互联网特别火爆,很多企业公司也都想拥有一个属于自己的ap ...

  3. [选择排序] 时间复杂度O(n^2)

    思路:从未排序的序列中,找到最小的元素,放到序列的起始位置, 再从剩下没排序的里面,找到最小的,放到已经排序的末尾. 原地操作几乎是选择排序的唯一优点,当空间复杂度要求较高时,可以考虑选择排序:实际适 ...

  4. 两个div并列居中显示——当display:inline-block;时,两个div无法对齐即一高一矮

    解决办法: 给div添加样式vertical-align: top;

  5. Codeforces Round #319 (Div. 2) B Modulo Sum (dp,鸽巢)

    直接O(n*m)的dp也可以直接跑过. 因为上最多跑到m就终止了,因为前缀sum[i]取余数,i = 0,1,2,3...,m,有m+1个余数,m的余数只有m种必然有两个相同. #include< ...

  6. UVA 1153 Keep the Customer Satisfied 顾客是上帝(贪心)

    因为每增加一个订单,时间是会增加的,所以先按截止时间d排序, 这样的话无论是删除一个订单,或者增加订单,都不会影响已经选好的订单. 然后维护一个已经选好的订单的大根堆(优先队列),如果当前无法选择的话 ...

  7. 2018.5.8 XML编程

    1.XML的概念 XML(Extensible Markup Language)可扩展性标记语言是一套定义语义标记的规则,这些标记将文档分成许多部件并对这些部件加以标识. 可拓展性标记语言是SGML( ...

  8. HTML_2

    html图像 <img>标签可以在网页上插入一张图片,它是独立使用的标签,通过‘src’属性定义图片的地址(可为绝对路径也可为相对路径),通过‘alt’属性定义图片加载时显示的文字,以及对 ...

  9. 完整的.h宏定义

    ##封装中的要点 __declspec(dllexport) 表明函数为导出函数 * `extern "C"` 导出的函数名与声明一致,否则导出函数名无法正常使用 当然,也可以通过 ...

  10. NSXMLParser

    NSXMLParser的使用 2011-05-05 15:50:17|  分类: 解析|字号 订阅     NSXMLParser解析xml格式的数据 用法如下: 首先,NSXMLParser必须继续 ...