poj3580:SuperMemo(块状链表/Splay)
传送门
- 题意:
题目要求实现一种数据结构,支持6种操作:
add x,y D:第x个数到第y个数之间的数每个加D;
reverse x y:第x个数到第y个数之间全部数翻转;
revolve x y T:第x个数到第y个数之间的数,向后循环流动T次,即后面T个数变成这段子序列的最前面T个,前面的被挤到后面。
Insert x P:在第x个数后面插入一个数P。
Delete x:删除第x个数。
Min x,y:求第x个数到第y个数之间的最小数字。
- 题解
1.块状链表。这是很好想而且很好写的,全是暴力操作。感兴趣的可以自己学习学习。(1400ms)
2.Splay。虽然时间复杂度比块状链表优(1087ms,其实也没优什么,主要是Splay常数大),但是代码特别长(块状链表250行,Splay400行)。用Splay主要注意两点,一是打标记(Add,Reverse操作),二是提取区间(即要操作的区间),提取方法很简单,将区间前一位置于rt,将区间后一位置于rt的右儿子,那么对rt右儿子的左儿子操作即可。
主要是Revolve操作有点难写,下面给出做法:
很显然是将[r-c+1,r]的区间提取到[l,r-c]之前,那么先提取前面的区间,再将l-1置为根节点,将l置为l-1的右儿子,将刚才提取的区间置为l左儿子即可。
(注意判断边界以及及时更新。。。)
- Code1(块状链表):1454MS
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std; inline int read();
const int N = 1e5 + 5, INF = 0x7fffffff, SIZEINT = sizeof(int);
const int SQRTN = 500, B = 1000, SMIN = SQRTN / 2, SMAX = SQRTN * 2;
int n, m, a[N]; typedef struct Block* PBlock;
typedef struct List* PList;
struct Block
{ int a[SQRTN * 5]; int size, tag, rev, ans; inline void calc() { tag = rev = 0; ans = INF; for (int i = 0; i < size; ++i) if (a[i] < ans) ans = a[i]; } inline void downdate() { if (tag != 0){ for (int i = 0; i < size; ++i)a[i] += tag; tag = 0; } if (rev){ rev = 0; for (int i = 0; i << 1 < size; ++i){ int t = a[i]; a[i] = a[size - i - 1]; a[size - i - 1] = t; } } }
}used[B]; PBlock pool, *top, unused[B];
struct List
{ PBlock a; PList last, next;
}USED[B]; PList head, tail, POOL, *TOP, UNUSED[B]; inline PBlock newBlock()
{ if (top != unused) return *--top; return pool++;
} inline void delBlock(PBlock x)
{ *top++ = x;
} inline PList newList()
{ if (TOP != UNUSED) return *--TOP; return POOL++;
} inline void delList(PList x)
{ *TOP++ = x;
} inline void Build(int *a, const int &n, PList *h, PList *t)
{ for (int i = 0; i < n; i += SQRTN) { PList p = newList(); p->a = newBlock(); p->a->size = i + SQRTN < n ? SQRTN : n - i; memcpy(p->a->a, a + i, SIZEINT * p->a->size); p->a->calc(); p->last = *t; p->next = NULL; if (*t != NULL) (*t)->next = p; else *h = p; *t = p; }
} inline void merge(PList x)
{ PList p = x->next; x->a->downdate(); p->a->downdate(); memcpy(x->a->a + x->a->size, p->a->a, SIZEINT * p->a->size); x->a->size += p->a->size; x->a->calc(); x->next = p->next; if (p->next) p->next->last = x; else tail = x; delBlock(p->a); delList(p);
} inline void split(PList x, const int &n)
{ PList p = newList(); p->a = newBlock(); x->a->downdate(); p->a->size = x->a->size - n; memcpy(p->a->a, x->a->a + n, SIZEINT * p->a->size); x->a->size = n; x->a->calc(); p->a->calc(); p->next = x->next; if (x->next) x->next->last = p; else tail = p; x->next = p; p->last = x;
} inline void Balance()
{ for (PList p = head; p; p = p->next) { while (p != tail && p->a->size < SMIN)merge(p); if (p->a->size > SMAX)split(p, SQRTN); }
} inline void Delete(PList x)
{ if (x->last != NULL) x->last->next = x->next; else head = x->next; if (x->next != NULL) x->next->last = x->last; else tail = x->last; delBlock(x->a); delList(x);
} inline PList findl(int n)
{ PList p = head; for (; n > p->a->size; p = p->next) n -= p->a->size; if (n != 1) { split(p, n - 1); p = p->next; } return p;
} inline PList findr(int n)
{ PList p = head; for (; n > p->a->size; p = p->next) n -= p->a->size; if (n != p->a->size) split(p, n); return p;
} inline void Init()
{ pool = used; POOL = USED; top = unused; TOP = UNUSED; head = tail = NULL;
} char ch;
inline int read()
{ int res = 0, sgn = 0; while (ch = getchar(), ch < '0' || ch > '9') if (ch == '-') sgn = 1; res = ch - 48; while (ch = getchar(), ch >= '0' && ch <= '9') res = res * 10 + ch - 48; return sgn ? -res : res;
} int main()
{ Init(); n = read(); for (int i = 0; i < n; ++i) a[i] = read(); Build(a, n, &head, &tail); m = read(); char type; int l, r, v; PList fr, en, t; PBlock tmp; while (m--) { Balance(); while (type = getchar(), type < 'A' || type > 'Z'); if (type == 'A') { l = read(); r = read(); v = read(); if (l > r) swap(l, r); fr = findl(l); en = findr(r); for (en = en->next; fr != en; fr = fr->next) { fr->a->tag += v; fr->a->ans += v; } } else if (type == 'I') { l = read(); r = read(); fr = findr(l); fr->a->downdate(); fr->a->a[fr->a->size++] = r; if (r < fr->a->ans) fr->a->ans = r; } else if (type == 'D') { l = read(); fr = findl(l); if (fr->a->size != 1) split(fr, 1); Delete(fr); } else if (type == 'M') { l = read(); r = read(); if (l > r) swap(l, r); fr = findl(l); en = findr(r); int ans = INF; for (en = en->next; fr != en; fr = fr->next) if (fr->a->ans < ans) ans = fr->a->ans; printf("%d\n", ans); } else { getchar(); getchar(); type = getchar(); if (type == 'E') { l = read(); r = read(); if (l > r) swap(l, r); fr = findl(l); en = findr(r); while (fr != en && fr != en->next) { fr->a->rev ^= 1; en->a->rev ^= 1; tmp = fr->a; fr->a = en->a; en->a = tmp; fr = fr->next; en = en->last; } if (fr == en) fr->a->rev ^= 1; } else { l = read(); r = read(); if (l > r) swap(l, r); v = read() % (r - l + 1); if (v == 0 || l == r) continue; v = r - l + 1 - v; fr = findl(l); en = findr(r); for (t = fr; v > t->a->size; t = t->next) v -= t->a->size; if (v != t->a->size) { split(t, v); if (en == t) en = en->next; } PList p1 = fr->last, p2 = fr, p3 = t, p4 = t->next, p5 = en, p6 = en->next; if (p1 != NULL) { p1->next = p4; p4->last = p1; } else head = p4, p4->last = NULL; if (p6 != NULL){ p6->last = p3; p3->next = p6; } else tail = p3, p3->next = NULL; p5->next = p2; p2->last = p5; } } } return 0;
}
- Code2(Splay):1047ms
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int Maxn=2e5+50;
const int INF=0x3f3f3f3f;
inline int read()
{char ch=getchar();int i=0,f=1;while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=getchar();}return i*f;
}struct node
{node *fa,*lc,*rc;int val,taga,tagr,mn,sze;node():fa(NULL),lc(NULL),rc(NULL){}inline void upt(){sze=(lc?lc->sze:0)+(rc?rc->sze:0)+1;mn=min(val,min(lc?lc->mn:INF,rc?rc->mn:INF));}
}POOL[Maxn],*pool=POOL,*rt,*que[Maxn];int n,m,a[Maxn],bg,ed;
char ch[10];inline void add(node *now,int val)
{now->val+=val;now->mn+=val;now->taga+=val;
}inline void addr(node *now)
{swap(now->lc,now->rc);now->tagr^=1;
}inline node* newnode(int val)
{++pool;pool->val=val;pool->mn=val;pool->sze=1;return pool;
}inline void build(node *&now,int l,int r)
{int mid=(l+r)>>1;now=newnode(a[mid]);if(l<mid)build(now->lc,l,mid-1);if(r>mid)build(now->rc,mid+1,r);if(now->lc)now->lc->fa=now;if(now->rc)now->rc->fa=now;now->upt();
}inline void pushdown(node *now)
{if(now->taga){if(now->lc){now->lc->mn+=now->taga;now->lc->val+=now->taga;now->lc->taga+=now->taga;}if(now->rc){now->rc->mn+=now->taga;now->rc->val+=now->taga;now->rc->taga+=now->taga;}now->taga=0;}if(now->tagr){if(now->lc){swap(now->lc->lc,now->lc->rc);now->lc->tagr^=1;}if(now->rc){swap(now->rc->lc,now->rc->rc);now->rc->tagr^=1;}now->tagr^=1; }
}inline node* find(node *now,int k)
{pushdown(now);now->upt();if((now->lc?now->lc->sze:0)==k-1)return now;else if((now->lc?now->lc->sze:0)>k-1)return find(now->lc,k);else return find(now->rc,k-(now->lc?now->lc->sze:0)-1);
}inline void Rotate(node *x)
{node *y=x->fa,*z=y->fa;y->fa=x;x->fa=z;if(z){((z->lc==y)?(z->lc):(z->rc))=x;}if(y->lc==x){node* b=x->rc;if(b)b->fa=y;y->lc=b;x->rc=y;}else{node* b=x->lc;if(b)b->fa=y;y->rc=b;x->lc=y;}y->upt();x->upt();
}inline bool which(node* x)
{return x->fa->lc==x;
}inline void Splay(node* x,node* tar=NULL)
{que[ed=1]=x;for(node* y=x;y!=rt;y=y->fa)que[++ed]=y->fa;for(int i=ed;i>=1;i--){node* y=que[i];pushdown(y);}while(x->fa!=tar){node* y=x->fa,*z=y->fa;if(z!=tar){if(which(x)^which(y))Rotate(x);else Rotate(y);}Rotate(x);}if(!tar)rt=x;
}inline node* split(int l,int r)
{if(l&&r<=n){node *t1=find(rt,l);node *t2=find(rt,r);Splay(t1);Splay(t2,rt);node *t3=t2->lc;t2->lc=NULL;t2->upt();t3->fa=NULL;return t3;}else if(!l){node *t2=find(rt,r);Splay(t2);node *t3=t2->lc;t2->lc=NULL;t2->upt();t3->fa=NULL;return t3;}else{node *t1=find(rt,l);Splay(t1);node *t3=t1->rc;t3->fa=NULL;t1->rc=NULL;t1->upt();return t3;}
}int buf[50];
inline void W(int x)
{if(!x){putchar('0');return;}if(x<0)putchar('-'),x=-x;while(x)buf[++buf[0]]=x%10,x/=10;while(buf[0])putchar('0'+buf[buf[0]--]);return;
}int main()
{n=read();for(int i=1;i<=n;i++){a[i]=read();}build(rt,1,n);m=read();while(m--){scanf("%s",ch+1);if(ch[1]=='A'){int l=read(),r=read(),v=read();if(l==1&&r==n)add(rt,v);else if(l==1){node* t2=find(rt,r+1);Splay(t2);add(rt->lc,v);rt->upt();}else if(r==n){node* t1=find(rt,l-1);Splay(t1);add(rt->rc,v);rt->upt();}else {node* t1=find(rt,l-1);node* t2=find(rt,r+1);Splay(t1);Splay(t2,rt);add(t2->lc,v);t2->upt();t1->upt();}}else if(ch[1]=='I'){int x=read(),y=read();if(x!=0&&x!=n){node* t1=find(rt,x);node* t2=find(rt,x+1);Splay(t1);Splay(t2,rt);t2->lc=newnode(y);t2->lc->fa=t2;t2->upt();t1->upt();n++;}else if(x!=0){node* t1=find(rt,x);Splay(t1);t1->rc=newnode(y);t1->rc->fa=t1;t1->upt();n++;}else{node* t2=find(rt,x+1);t2->lc=newnode(y);t2->lc->fa=t2;t2->upt();n++;} }else if(ch[1]=='D'){int pos=read();if(pos!=1&&pos!=n){node* t1=find(rt,pos-1);node* t2=find(rt,pos+1);Splay(t1);Splay(t2,rt);t2->lc->fa=NULL;t2->lc=NULL;t2->upt();rt->upt();n--;}else if(pos!=1){node* t1=find(rt,pos-1);Splay(t1);t1->rc->fa=NULL;t1->rc=NULL;t1->upt();n--;}else{node* t2=find(rt,pos+1);Splay(t2);t2->lc->fa=NULL;t2->lc=NULL;t2->upt();n--;}}else if(ch[1]=='M'){int l=read(),r=read();if(l==1&&r==n)W(rt->mn),putchar('\n');else if(l==1){node* t2=find(rt,r+1);Splay(t2);W(rt->lc->mn),putchar('\n');}else if(r==n){node* t1=find(rt,l-1);Splay(t1);W(rt->rc->mn),putchar('\n');}else {node* t1=find(rt,l-1);node* t2=find(rt,r+1);Splay(t1);Splay(t2,rt);W(t2->lc->mn),putchar('\n');}}else if(ch[4]=='E'){int l=read(),r=read();if(l==1&&r==n)addr(rt);else if(l==1){node* t2=find(rt,r+1);Splay(t2);addr(rt->lc);}else if(r==n){node* t1=find(rt,l-1);Splay(t1);addr(rt->rc);}else {node* t1=find(rt,l-1);node* t2=find(rt,r+1);Splay(t1);Splay(t2,rt);addr(t2->lc);}}else{int x=read(),y=read(),c=read();int l=(y-x+1);c%=l;if(c==0)continue;node* t1=split(y-c,y+1);if(x!=1){node* t2=find(rt,x-1);node* t3=find(rt,x);Splay(t2);Splay(t3,rt);t3->lc=t1;t1->fa=t3;t3->upt();t2->upt();}else{node* t3=find(rt,x);Splay(t3);t3->lc=t1;t1->fa=t3;t3->upt();}}}
}
poj3580:SuperMemo(块状链表/Splay)相关推荐
- Splay ---- 2018牛客多校第三场 区间翻转搞区间位移 或者 rope可持久化块状链表
题目链接 题目大意: 就是每次把牌堆中若干个连续的牌放到堆顶,问你最后牌的序列. 解题思路: Splay 区间翻转的模板题: 对于一个区间[1,2,3,4,5,6,7,8][1,2,3,4,5,6,7 ...
- 【Splay】【块状链表】bzoj3223 Tyvj 1729 文艺平衡树
让蒟蒻见识到了常数大+滥用STL的危害. <法一>很久之前的Splay #include<cstdio> #include<algorithm> using nam ...
- 块状链表(附NOI 2003 Editor,POJ 2131 Key Insertion)
这两天学习了一下块状链表,也谈不上学习,可以说是练习.因为块状链表这种东西,猛一听起来好像很高端,但是拆开来说就是:分块+链表.根本上就是暴力,就是分块.只不过"分"的对象从数组变 ...
- [BZOJ3337] ORZJRY I --块状链表大毒瘤
link 题目大意:维护一个序列 支持: 1.单点插入 2.单点删除 3.区间翻转 4.区间旋转 5.区间加 6.区间赋值 7.询问区间和 8.询问区间极差 9.询问区间与给定某个数差值绝对值的最小值 ...
- 【POJ2887】Big String(块状链表,模板)
problem 给一个字符串,长度不超过 1e6,有两种操作: 在第 i 个字符的前面添加一个字符 ch 查询第 k 个位置是什么字符 操作的总数不超过 2000 solution 1.传统的数组所有 ...
- Python数据结构与算法(附录)——块状链表的动态调整
Python数据结构与算法(附录)--块状链表的动态调整 块状链表的动态调整 违反规则 1 违反规则 2 相关链接 块状链表的动态调整 我们已经知道块状链表的块的最大容量会随着链表长度的变化动态改变, ...
- 【数据结构与算法】 01 链表 (单链表、双向链表、循环链表、块状链表、头结点、链表反转与排序、约瑟夫环问题)
一.线性表 1.1 概念与特点 1.2 线性表的存储结构 1.3 常见操作 1.4 应用场景 二.链表 2.1 链表简介 2.2 单向链表(单链表) 2.21 基本概念 2.22 单链表基本操作 2. ...
- Python数据结构与算法(2.6)——块状链表
Python数据结构与算法(2.6)--块状链表 0. 学习目标 1. 块状链表简介 1.1 块状链表介绍 1.2 块状链表中结点类 1.3 块状链表中块类 2. 块状链表的实现 2.1 块状链表的初 ...
- 块状链表(STL rope)
块状链表(STL rope) 首先介绍一下块状链表. 我们都知道: 数组 具有 O(1)的查询时间,O(N)的删除,O(N)的插入. 链表 具有 O(N)的查询时间,O(1)的删除,O(1)的插入. ...
- 高级打字机【主席树】【滚动数组】【块状链表】
题目大意: 一个计算机支持一下三中操作: TT xx:在文章末尾打下一个小写字母xx. UU xx:撤销最后的xx次修改操作. QQ xx:询问当前文章中第xx个字母并输出. InputInput 7 ...
最新文章
- nginx 负载均衡的4种方式
- RxJS实践,Vue如何集成RxJS
- 在ubuntu上安装apc扩展
- 信号处理的流程linux,linux信号处理机制
- 1700x关闭超线程超频_转发分享一个超频技术新手知识BIOS设置指南
- 2.3 指数加权平均
- STM32|4-20mA输出电路
- java技术类网站收录
- Topic Model的分类总结(LDA变种)
- 牛客网 2018校招真题 吉比特 最大差值
- c51单片机音乐门铃C语言程序,基于51单片机的无线音乐门铃设计
- 【PHPWord】PHPWord生成图表-雷达图 | 隐藏图例、设置数值类别隐藏、展示多组数据
- 爬虫数据云词图片怎么做?小姐姐教你用python做B站弹幕爬虫,并进行数据分析生成词云
- 数字信号处理matlab相关实验
- Python之父-Guido van Rossum
- 互联网时代中医药产业复兴的科技创新
- python必备第三方库-20个必不可少的Python库也是基本的第三方库
- 向凡客提议:建立ERP 深挖服装市场价值
- IKAnalyzer 中文分词器
- 格式工厂转换视频找不到视频无法添加错误