Description

Your friend, Jackson is invited to a TV show called SuperMemo in which the participant is told to play a memorizing game. At first, the host tells the participant a sequence of numbers, {A1A2, ... An}. Then the host performs a series of operations and queries on the sequence which consists:

  1. ADD x y D: Add D to each number in sub-sequence {Ax ... Ay}. For example, performing "ADD 2 4 1" on {1, 2, 3, 4, 5} results in {1, 3, 4, 5, 5}
  2. REVERSE x y: reverse the sub-sequence {Ax ... Ay}. For example, performing "REVERSE 2 4" on {1, 2, 3, 4, 5} results in {1, 4, 3, 2, 5}
  3. REVOLVE x y T: rotate sub-sequence {Ax ... AyT times. For example, performing "REVOLVE 2 4 2" on {1, 2, 3, 4, 5} results in {1, 3, 4, 2, 5}
  4. INSERT x P: insert P after Ax. For example, performing "INSERT 2 4" on {1, 2, 3, 4, 5} results in {1, 2, 4, 3, 4, 5}
  5. DELETE x: delete Ax. For example, performing "DELETE 2" on {1, 2, 3, 4, 5} results in {1, 3, 4, 5}
  6. MIN x y: query the participant what is the minimum number in sub-sequence {Ax ... Ay}. For example, the correct answer to "MIN 2 4" on {1, 2, 3, 4, 5} is 2

To make the show more interesting, the participant is granted a chance to turn to someone else that means when Jackson feels difficult in answering a query he may call you for help. You task is to watch the TV show and write a program giving the correct answer to each query in order to assist Jackson whenever he calls.

Input

The first line contains (≤ 100000).

The following n lines describe the sequence.

Then follows M (≤ 100000), the numbers of operations and queries.

The following M lines describe the operations and queries.

Output

For each "MIN" query, output the correct answer.

Sample Input

5
1
2
3
4
5
2
ADD 2 4 1
MIN 4 5

Sample Output

5

Source

【分析】
真实蛋疼了。。
第一次写的时候居然犯了一个傻逼到极点的错误。。。。
翻转部分不会,是看别人的。不过感觉应该还有不同的写法。
代码写得比较丑,主要是尝试了引用。
 #include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <utility>
#include <iomanip>
#include <string>
#include <cmath>
#include <queue>
#include <assert.h>
#include <map>
#include <ctime>
#include <cstdlib>
#define LOCAL
const int MAXN = + ;
const int INF = ;
const int SIZE = ;
const int maxnode = 0x7fffffff + ;
using namespace std;
struct SPLAY{
struct Node{
int val, Min;//分别为值,最小值,大小和lazy下标
int size, lazy;
bool turn;
Node *parent, *ch[]; //初始化
void NEW(int x){
Min = val = x;
size = ;
lazy = turn = ;
parent = ch[] = ch[] = NULL;
}
int cmp(){
if (parent->ch[] == this) return ;
if (parent->ch[] == this) return ;
}
//还是不要写在里面了..
/*void pushdown(){ }
void update(){
size = 1;
if (x->ch[0] != NULL) size += x->ch[0]->size;
if (x->ch[1] != NULL) size += x->ch[0]->size;
}
*/
}mem[MAXN], *root;//mem为静态数组
int tot; int get(Node *&x){return (x == NULL ? : x->size);}
//————————————————————这一部分不能卸载里面
//更新
void update(Node *&x){
if (x == NULL) return;
x->size = ;
x->Min = x->val;
if (x->ch[] != NULL) {x->Min = min(x->Min, x->ch[]->Min);x->size += x->ch[]->size;}
if (x->ch[] != NULL) {x->Min = min(x->Min, x->ch[]->Min);x->size += x->ch[]->size;}
}
void pushdown(Node *&x){//标记下传
if (x == NULL) return;
if (x->lazy){
int tmp = x->lazy;
x->val += tmp;
if (x->ch[] != NULL) {x->ch[]->lazy += tmp;x->ch[]->Min += tmp;}
if (x->ch[] != NULL) {x->ch[]->lazy += tmp;x->ch[]->Min += tmp;}
x->lazy = ;
}
if (x->turn){//翻转
swap(x->ch[], x->ch[]);//swap内部用什么实现的呢? if (x->ch[] != NULL) x->ch[]->turn ^= ;
if (x->ch[] != NULL) x->ch[]->turn ^= ;
x->turn = ;
}
} //————————————————————————————
//旋转,1为右旋, 0为左旋
void Rotate(Node *&x, int d){//不用引用也可以
Node *y = x->parent;
pushdown(y);//注意顺序
pushdown(x);
pushdown(x->ch[d]);//这个不要忘了 y->ch[d ^ ] = x->ch[d];
if (x->ch[d] != NULL) x->ch[d]->parent = y;
x->parent = y->parent;
if (y->parent != NULL){
if (y->parent->ch[] == y) y->parent->ch[] = x;
else y->parent->ch[] = x;
}
x->ch[d] = y;
y->parent = x;
update(y);
if (y == root) root = x;//如果是引用要小心root被传下去
}
void debug(){
Node *p = new Node;
root = new Node;
root->ch[] = p;
p->parent = root;
printf("%d", p->cmp());
}
//注意我写的这个跟下午那个不一样,下午那个好麻烦
void splay(Node *&x, Node *&y){
pushdown(x);
while (x != y){
if(x->parent == y){
if (y->ch[] == x) Rotate(x, );
else Rotate(x,);
break;
}else{
Node *y = x->parent, *z = y->parent;//注意一定要这样弄一下
if (z->ch[] == y)
if (y->ch[] == x) Rotate(y,),Rotate(x, );
else Rotate(x, ), Rotate(x, );
else if (y->ch[] == x) Rotate(y, ), Rotate(x, );
else Rotate(x, ), Rotate(x, );
if (z == y) break;
}
update(x);
}
update(x);
}
//寻找第k大
void find(Node *&t, int k){
int tmp;
Node *p = root;
while (){
pushdown(p);
tmp = get(p->ch[]);
if (k == (tmp + )) break;
if (k <= tmp) p = p->ch[];
else {k -= tmp + , p = p->ch[];}
}
pushdown(p);
splay(p, t);
}
//插入操作
void Insert(int pos, int val){
//还是卡出来
find(root, pos + );
find(root->ch[], pos + );
Node *t = &mem[tot++], *x = root->ch[];
pushdown(root);
pushdown(x);
t->NEW(val);
//直接拆开放中间,放在root->ch[1]->ch[0]应该也可以
t->ch[] = x;
x->parent = t;
root->ch[] = t;
t->parent = root;
splay(x, root);
}
//区间加
void Add(int l, int r, int x){
find(root, l);
find(root->ch[] , r + );
Node *t = root->ch[]->ch[];
pushdown(t);
update(t);
t->Min += x;
t->lazy += x;
splay(t, root);
}
//翻转操作
void Reverse(int l, int r){
find(root, l);
find(root->ch[], r + );
root->ch[]->ch[]->turn ^= ;
Node *x = root->ch[]->ch[];
splay(x, root);
}
//交换操作,这一段我是看别人的....
void Revolve(int l, int r, int t){
Node *p1, *p2; find(root, l);
find(root->ch[], r + );
find(root->ch[]->ch[], r + - t); p1 = root->ch[]->ch[];
pushdown(p1);
p2 = p1->ch[];
p1->ch[] = NULL;
find(root->ch[]->ch[], l + );
p1 = root->ch[]->ch[];
pushdown(p1);
p1->ch[] = p2;
p2->parent = p1;
splay(p2, root);
}
int getMin(int l, int r){
find(root, l);
find(root->ch[], r + );
Node *x = root->ch[];
pushdown(x);
x = x->ch[];
pushdown(x);
update(x);
return x->Min;
}
void Erase(int pos){//删除
find(root, pos);
find(root->ch[], pos + );
pushdown(root->ch[]);
root->ch[]->ch[] = NULL;
Node *x = root->ch[];
splay(x, root);
}
void init(){
//注意还要加一个正无穷
tot = ;
root = &mem[tot++];
root->NEW(INF);
root->ch[] = &mem[tot++];
root->ch[]->NEW(INF);
}
void print(Node *t){
if (t == NULL) return;
print(t->ch[]);
printf("%d ", t->val);
if (t->parent != NULL) printf("%d\n", t->parent->val);
print(t->ch[]);
}
}A; int n, m;
//注意在这里为了防止掉到0,所以每个位置都要+1
void init(){//初始化
A.init();
scanf("%d", &n);
for (int i = ; i < n; i++){
int x;
scanf("%d", &x);
A.Insert(i, x);
//printf("%d\n", A.root->val);
}
//A.print(A.root);
}
void work(){
scanf("%d", &m);
for (int i = ; i <= m; i++){//询问,按顺序来。。
char str[];
scanf("%s", str);
if (str[] == 'A'){
int l, r, x;
scanf("%d%d%d", &l, &r, &x);
A.Add(l, r, x);
}else if (str[] == 'R'){
int l, r;
scanf("%d%d", &l, &r);
if (str[] == 'E') A.Reverse(l, r);
else{
int x, len;
scanf("%d", &x);
len = r - l + ;
x = (x % len + len) % len;
if (x == || l == r) continue;//我开始居然傻逼的写在前面....
A.Revolve(l, r, x);
}
}else if (str[] == 'I'){
int l, x;
scanf("%d%d", &l, &x);
A.Insert(l, x);
}else if (str[] == 'D'){
int l;
scanf("%d", &l);
A.Erase(l);
}else if (str[] == 'M'){
int l, r;
scanf("%d%d", &l, &r);
printf("%d\n", A.getMin(l, r));
}
}
}
void debug(){ } int main(){ init();
work();
//debug();
//A.debug();
return ;
}

【POJ3580】【splay版】SuperMemo的更多相关文章

  1. poj3580 splay树 REVOVLE循环

    SuperMemo Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 12795   Accepted: 3989 Case T ...

  2. [P3369]普通平衡树(Splay版)

    模板,不解释 #include<bits/stdc++.h> using namespace std; const int mxn=1e5+5; int fa[mxn],ch[mxn][2 ...

  3. bzoj1861 书架 splay版

    单点插入删除以及求前缀 #include<cstdio> #include<cstring> #include<algorithm> using namespace ...

  4. bzoj1503 郁闷的出纳员 splay版

    自己yy的写法 可能有点奇怪吧 详情看代码 还是蛮短的 #include<cstdio> #include<cstring> #include<algorithm> ...

  5. splay版

    指针是个好东西 不过就是得判空 还有别忘传引用(其实应该都传引用) #include<cstdio> #include<algorithm> #include<iostr ...

  6. AC日记——营业额统计 codevs 1296 (splay版)

    营业额统计 思路: 每次,插入一个点: 然后找前驱后继: 来,上代码: #include <cmath> #include <cstdio> #include <iost ...

  7. 数列[专杀Splay版]

    时间限制: 3 Sec  内存限制: 128 MB提交: 49  解决: 7 题目描述 输入一个数列,你需要进行如下操作:  1. 把编号为I的数值改为K  2. 输出从小到大排序后第k个数 输入 输 ...

  8. 牛客网多校训练第三场 C - Shuffle Cards(Splay / rope)

    链接: https://www.nowcoder.com/acm/contest/141/C 题意: 给出一个n个元素的序列(1,2,...,n)和m个操作(1≤n,m≤1e5),每个操作给出两个数p ...

  9. BZOJ2028:[SHOI2009]会场预约(平衡树版)

    浅谈\(splay\):https://www.cnblogs.com/AKMer/p/9979592.html 浅谈\(fhq\)_\(treap\):https://www.cnblogs.com ...

随机推荐

  1. Linux下高效编写Shell——shell特殊字符汇总

    Linux下无论如何都是要用到shell命令的,在Shell的实际使用中,有编程经验的很容易上手,但稍微有难度的是shell里面的那些个符号,各种特殊的符号在我们编写Shell脚本的时候如果能够用的好 ...

  2. pm grant 命令

    CustomLocale.apk所需要的权限"android.permission.CHANGE_CONFIGURATION"自Android 4.2,4.2.2起系统定义为and ...

  3. Linux学习笔记23——取消线程

    一 相关函数 1 发送终止信号 #include <pthread.h> int pthread_cancel(pthread_t thread); 2 设置取消状态 #include & ...

  4. HTML-通过点击网页上的文字弹出QQ添加好友页面

    在网上参考了部分方法,综合了一下. 发现有2中方式: 第一种是不能直接弹出添加界面的,只能弹出网页,再通过网页中的添加好友才能添加: 弹出的网页是这样的(我是写成在新的网页中打开) 现在看实现的代码: ...

  5. leetcode shttps://oj.leetcode.com/problems/surrounded-regions/

    1.从外围搜索O,深度搜索出现了 Line 35: java.lang.StackOverflowError Last executed input: ["OOOOOOOOOOOOOOOOO ...

  6. string.Format字符串格式说明

    先举几个简单的应用案例: 1.格式化货币(跟系统的环境有关,中文系统默认格式化人民币,英文系统格式化美元) string.Format("{0:C}",0.2) 结果为:¥0.20 ...

  7. c#基础语言编程-正则表达式应用

    引言 在不同语言中虽正则表达式一样,但应用函数还是有所区别,在c#语言中使用Regex. 可以通过以下两种方式之一使用正则表达式引擎: 通过调用 Regex 类的静态方法. 方法参数包含输入字符串和正 ...

  8. Hadoop平台提供离线数据和Storm平台提供实时数据流

    1.准备工作 2.一个Storm集群的基本组件 3.Topologies 4.Stream 5.数据模型(Data Model) 6.一个简单的Topology 7.流分组策略(Stream grou ...

  9. Android 仿PhotoShop调色板应用(三) 主体界面绘制

    版权声明:本文为博主原创文章,未经博主允许不得转载. Android 仿PhotoShop调色板应用(三) 主体界面绘制    关于PhotoShop调色板应用的实现我总结了两个最核心的部分:   1 ...

  10. android 55

    智能家居:可以联网可以用指令操作可以返回状态.智能微波炉智能眼镜智能手表. Android作者Andy Rubin,2007年正式由谷歌推广,开源的. 安卓体系结构和开发一个闹钟的调用结构图: 安卓和 ...