SuperMemo

题目链接

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, {A1, A2, ... An}. Then the host performs a series of operations and queries on the sequence which consists:

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}

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}

REVOLVE x y T: rotate sub-sequence {Ax ... Ay} T times. For example, performing "REVOLVE 2 4 2" on {1, 2, 3, 4, 5} results in {1, 3, 4, 2, 5}

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}

DELETE x: delete Ax. For example, performing "DELETE 2" on {1, 2, 3, 4, 5} results in {1, 3, 4, 5}

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 n (n ≤ 100000).

The following n lines describe the sequence.

Then follows M (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

解题思路:

裸的splay,就是代码量有点大

#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <set>
#include <vector>
#include <cctype>
#include <iomanip>
#include <sstream>
#include <climits>
#include <queue>
#include <stack>
using namespace std;
/* freopen("k.in", "r", stdin);
freopen("k.out", "w", stdout); */
//clock_t c1 = clock();
//std::cerr << "Time:" << clock() - c1 <<"ms" << std::endl;
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#define de(a) cout << #a << " = " << a << endl
#define rep(i, a, n) for (int i = a; i <= n; i++)
#define per(i, a, n) for (int i = n; i >= a; i--)
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef vector<int, int> VII;
#define inf 0x3f3f3f3f
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll MAXN = 1e6 + 7;
const ll MAXM = 5e6 + 7;
const ll MOD = 1e9 + 7;
const double eps = 1e-6;
const double pi = acos(-1.0);
int root = 0, N, tot = 0; //tot 总结点数量
int a[MAXN];
struct Node
{
int ch[2]; //子节点
int ff; //父节点
int cnt; //数量
int val; //值
int size; //儿子以及自己的总元素数量
int rev; //lazy标记
int lazy;
int minn;
void init(int x, int fa)
{
ff = ch[0] = ch[1] = 0;
size = 1;
val = x;
ff = fa;
cnt = 1;
lazy = 0;
minn = x;
rev = 0;
}
} t[MAXN];
void push_up(int u)
{
t[u].size = t[t[u].ch[0]].size + t[t[u].ch[1]].size + t[u].cnt;
t[u].minn = t[u].val;
if (t[u].ch[0])
t[u].minn = min(t[u].minn, t[t[u].ch[0]].minn);
if (t[u].ch[1])
t[u].minn = min(t[u].minn, t[t[u].ch[1]].minn);
}
void push_down(int now)
{
if (t[now].rev)
{
t[t[now].ch[0]].rev ^= 1;
t[t[now].ch[1]].rev ^= 1;
t[now].rev = 0;
swap(t[now].ch[0], t[now].ch[1]);
}
if (t[now].lazy)
{
if (t[now].ch[0])
{
t[t[now].ch[0]].lazy += t[now].lazy;
t[t[now].ch[0]].val += t[now].lazy;
t[t[now].ch[0]].minn += t[now].lazy;
}
if (t[now].ch[1])
{
t[t[now].ch[1]].lazy += t[now].lazy;
t[t[now].ch[1]].val += t[now].lazy;
t[t[now].ch[1]].minn += t[now].lazy;
}
t[now].lazy = 0;
}
}
void rotate(int x) //旋转
{
register int y = t[x].ff;
register int z = t[y].ff;
register int k = t[y].ch[1] == x; //x是y的左或右儿子
t[z].ch[t[z].ch[1] == y] = x;
t[x].ff = z;
t[y].ch[k] = t[x].ch[k ^ 1];
t[t[x].ch[k ^ 1]].ff = y;
t[x].ch[k ^ 1] = y;
t[y].ff = x;
push_up(y);
push_up(x);
}
void Splay(int x, int goal) //把x节点旋转到目标位置
{
while (t[x].ff != goal)
{
int y = t[x].ff;
int z = t[y].ff;
if (z != goal) //旋转
(t[y].ch[0] == x) ^ (t[z].ch[0] == y) ? rotate(x) : rotate(y);
rotate(x);
}
if (goal == 0)
root = x; //当前的根节点
}
void init()
{
root = tot = 0;
}
int buildtree(int l, int r, int fa)
{
if (l > r)
return 0;
int mid = (l + r) >> 1;
t[++tot].init(a[mid], fa);
int x = tot;
t[x].ch[0] = buildtree(l, mid - 1, x);
t[x].ch[1] = buildtree(mid + 1, r, x);
push_up(x);
return x;
}
int Kth(int k) //查找排名为x的序号
{
int u = root;
while (233)
{
push_down(u);
if (t[t[u].ch[0]].size >= k)
u = t[u].ch[0];
else if (t[t[u].ch[0]].size + 1 == k)
return u;
else
k -= t[t[u].ch[0]].size + 1, u = t[u].ch[1];
}
}
void ADD(int l, int r, int v) //区间+v
{
l = Kth(l);
r = Kth(r + 2);
Splay(l, 0);
Splay(r, l);
t[t[r].ch[0]].val += v;
t[t[r].ch[0]].minn += v;
t[t[r].ch[0]].lazy += v;
push_up(r);
push_up(l);
}
void reverse(int l, int r) //区间翻转
{
l = Kth(l);
r = Kth(r + 2);
Splay(l, 0);
Splay(r, l);
t[t[r].ch[0]].rev ^= 1;
}
void revolve(int l, int r, int k) //区间旋转k次
{
k = (k % (r - l + 1) + (r - l + 1)) % (r - l + 1);
if (!k)
return;
int x = Kth(r - k + 1);
int y = Kth(r + 2);
//把整段区间拿到前面
Splay(x, 0);
Splay(y, x);
int temp = t[y].ch[0];
t[y].ch[0] = 0;
push_up(y);
push_up(x); x = Kth(l);
y = Kth(l + 1);
Splay(x, 0);
Splay(y, x);
t[y].ch[0] = temp;
t[temp].ff = y;
push_up(y);
push_up(x);
}
void Insert(int x, int v) //在第x数后面插入v
{
Splay(Kth(x + 1), 0);
Splay(Kth(x + 2), root);
t[++tot].init(v, t[root].ch[1]);
t[t[root].ch[1]].ch[0] = tot;
push_up(t[root].ch[1]);
push_up(root);
}
void del(int x)
{
Splay(Kth(x), 0);
Splay(Kth(x + 2), root);
t[t[root].ch[1]].ch[0] = 0;
push_up(t[root].ch[1]);
push_up(root);
}
int query(int l, int r)
{
int x = Kth(l);
int y = Kth(r + 2);
Splay(x, 0);
Splay(y, x);
return t[t[y].ch[0]].minn;
}
int main()
{
init();
int M;
scanf("%d", &N);
for (int i = 1; i <= N; i++)
scanf("%d", &a[i]);
a[0] = a[N + 1] = inf;
root = buildtree(0, N + 1, 0);
scanf("%d", &M);
while (M--)
{
char op[10];
scanf(" %s", op);
if (op[0] == 'A')
{
int l, r, v;
scanf("%d%d%d", &l, &r, &v);
ADD(l, r, v);
}
else if (op[0] == 'R' && op[3] == 'O')
{
int l, r, t;
scanf("%d%d%d", &l, &r, &t);
revolve(l, r, t);
}
else if (op[0] == 'R')
{
int l, r;
scanf("%d%d", &l, &r);
reverse(l, r);
}
else if (op[0] == 'I')
{
int k, v;
scanf("%d%d", &k, &v);
Insert(k, v);
}
else if (op[0] == 'D')
{
int x;
scanf("%d", &x);
del(x);
}
else
{
int l, r;
scanf("%d%d", &l, &r);
printf("%d\n", query(l, r));
}
}
return 0;
}

PKU-3580 SuperMemo(Splay模板题)的更多相关文章

  1. bzoj 1588 splay模板题

    用晚自习学了一下splay模板,没想象中那么难,主要是左旋和右旋可以简化到一个函数里边,减少代码长度... #include<iostream> #include<cstdio> ...

  2. 【BZOJ 3196】二逼平衡树 线段树套splay 模板题

    我写的是线段树套splay,网上很多人写的都是套treap,然而本蒟蒻并不会treap 奉上sth神犇的模板: //bzoj3196 二逼平衡树,支持修改某个点的值,查询区间第k小值,查询区间某个值排 ...

  3. bzoj 3224 splay模板题4

    再刷水题我就废了... #include<iostream> #include<cstdio> #include<algorithm> #include<cs ...

  4. bzoj 3223 splay模板题3

    水题...貌似理解splay怎么维护数列了... 每个点维护一个size,它的位置就是它的size,区间翻转的话可以打标记,find的时候push_down,交换左右子树. #include<i ...

  5. bzoj 1208 splay模板题2

    自己yy了找前驱和后继,学了学怎么删除...(反正就是练模板) #include<iostream> #include<cstdio> #include<cstring& ...

  6. 【BZOJ 3188】【Coci 2011】Upit Splay模板题

    转啊转终于转出来了,然而我的模板跟陈竞潇学长的模板一模一样,还是太弱啊,第一次用指针. #include<cstdio> #include<cstring> #include& ...

  7. BZOJ 1208 [HNOI2004]宠物收养所 | SPlay模板题

    题目: 洛谷也能评 题解: 记录一下当前树维护是宠物还是人,用Splay维护插入和删除. 对于任何一次询问操作都求一下value的前驱和后继(这里前驱和后继是可以和value相等的),比较哪个差值绝对 ...

  8. POJ 3580 - SuperMemo - [伸展树splay]

    题目链接:http://poj.org/problem?id=3580 Your friend, Jackson is invited to a TV show called SuperMemo in ...

  9. 【POJ 3580】SuperMemo Splay

    题意 给定$n$个数,$m$个询问,每次在$[L,R]$区间加上一个数,或者反转一个区间$[L,R]$,或者循环右移区间$[L,R]$共$T$次,或者在第$x$个数后插入一个数$p$,或者删除第$x$ ...

随机推荐

  1. slim中的参数获取

    官方文档中对于get和post的参数有以下获取方式 $app->get('/', function (Request $req, Response $res, $args = []) { $my ...

  2. 宣布一件事,通过写博客,挣到了人生的第一个 10w

    今天是 2019 年的最后一天,对于我来说,2019 年可以说是我高考进入大学以来,最重要的一年了.这一年,也是我收获最多的一年,其中最重要的收获应该就是『找工作』和『运营公众号』以及『挣到了人生的第 ...

  3. 【题解】LOJ2759. 「JOI 2014 Final」飞天鼠(最短路)

    [题解]LOJ2759. 「JOI 2014 Final」飞天鼠(最短路) 考虑最终答案的构成,一定是由很多飞行+一些上升+一些下降构成. 由于在任何一个点上升或者下降代价是一样的,所以: 对于上升操 ...

  4. 第 426 期 Python 周刊

    文章,教程和讲座 端到端机器学习:从数据收集到模型部署 链接: https://ahmedbesbes.com/end-to-end-ml.html 在本文中,我们将完成构建和部署机器学习应用程序的必 ...

  5. Spring Security入门(基于SSM环境配置)

    一.前期准备 配置SSM环境 二.不使用数据库进行权限控制 配置好SSM环境以后,配置SpringSecurity环境 添加security依赖   <dependency> <gr ...

  6. 1045 快速排序 (25 分)C语言

    著名的快速排序算法里有一个经典的划分过程:我们通常采用某种方法取一个元素作为主元,通过交换,把比主元小的元素放到它的左边,比主元大的元素放到它的右边. 给定划分后的 N 个互不相同的正整数的排列,请问 ...

  7. .NET Core 3.0 System.Text.Json 和 Newtonsoft.Json 行为不一致问题及解决办法

    行为不一致 .NET Core 3.0 新出了个内置的 JSON 库, 全名叫做尼古拉斯 System.Text.Json - 性能更高占用内存更少这都不是事... 对我来说, 很多或大或小的项目能少 ...

  8. Hadoop以及组件介绍

    一.背景介绍 在接触过大数据相关项目的时候常常都会听到Hadoop这个东西,简单来说,他是一个用分布式计算来处理大数据的开源软件,下面包含了许多的组件和子项目,这篇文章将会介绍Hadoop的原理以及一 ...

  9. Nginx流量复制

    1. 需求 将生产环境的流量拷贝到预上线环境或测试环境,这样做有很多好处,比如: 可以验证功能是否正常,以及服务的性能: 用真实有效的流量请求去验证,又不用造数据,不影响线上正常访问: 这跟灰度发布还 ...

  10. 深入浅出 Typescript 学习笔记

    TypeScript 是 JavaScript 的一个超集,支持 ECMAScript 6 标准. TypeScript 由微软开发的自由和开源的编程语言. TypeScript 设计目标是开发大型应 ...