poj3580 SuperMemo (Splay+区间内向一个方向移动)
Time Limit: 5000MS | Memory Limit: 65536K | |
Total Submissions: 13550 | Accepted: 4248 | |
Case Time Limit: 2000MS |
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, {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
题意:给你n个数组成的一个序列,让你写一个数据结构支持下列操作:1.区间[x,y]增加c 2.区间[x,y]翻转 3.区间[x,y]向右移动c次,如1 2 3 4 5向右移动2次就变成4 5 1 2 3。4.在第x个数后插入c 5.删除第x个数 6.求出区间[x,y]内的最小值。
思路:要维护rev[],mx[],add[]分别表示旋转标记,最小值以及成段增加的标记,然后这题和其他题不用的地方在于多了一个区间内移动的操作,我们要先求出c被y-x+1除后的余数,如果为0就不变,如果不为0,那么画图可以看出这个操作等价于把[y-c+1,y]移到[x,y-c]这个区间的前面,然后就可以直接做了。
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<string>
#include<bitset>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef long double ldb;
#define inf 99999999
#define pi acos(-1.0)
#define Key_value ch[ch[rt][1]][0]
#define maxn 1000010
int n;
int cnt,rt;
int pre[maxn],ch[maxn][2],sz[maxn],rev[maxn],zhi[maxn],mx[maxn],add[maxn];
int b[maxn],tot2;//内存池和容量
int a[maxn];
void update_rev(int x)
{
if(!x)return; //!!!
rev[x]^=1;
swap(ch[x][0],ch[x][1]);
}
void update_add(int x,int value)
{
zhi[x]+=value;
add[x]+=value;
mx[x]+=value;
}
void pushdown(int x)
{
if(rev[x]){
update_rev(ch[x][0]);
update_rev(ch[x][1]);
rev[x]=0;
}
if(add[x]){
update_add(ch[x][0],add[x]);
update_add(ch[x][1],add[x]);
add[x]=0;
}
}
void pushup(int x)
{
int t=zhi[x];
if(ch[x][0])t=min(t,mx[ch[x][0] ]);
if(ch[x][1])t=min(t,mx[ch[x][1] ]);
mx[x]=t;
sz[x]=sz[ch[x][0] ]+sz[ch[x][1] ]+1;
}
void Treavel(int x)
{
if(x)
{
pushdown(x);
Treavel(ch[x][0]);
printf("结点:%2d: 左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d zhi = %2d minx=%2d add=%2d\n",x,ch[x][0],ch[x][1],pre[x],sz[x],zhi[x],mx[x],add[x]);
Treavel(ch[x][1]);
}
}
void debug()
{
printf("root:%d\n",rt);
Treavel(rt);
}
void newnode(int &x,int father,int value)
{
if(tot2)x=b[tot2--];
else x=++cnt;
pre[x]=father;ch[x][0]=ch[x][1]=0;sz[x]=1;rev[x]=0;zhi[x]=value;mx[x]=value;add[x]=0;
}
void build(int &x,int l,int r,int father)
{
if(l>r)return;
int mid=(l+r)/2;
newnode(x,father,a[mid]);
build(ch[x][0],l,mid-1,x);
build(ch[x][1],mid+1,r,x);
pushup(x);
}
void init()
{
cnt=rt=tot2=0;
pre[0]=ch[0][0]=ch[0][1]=sz[0]=rev[0]=zhi[0]=mx[0]=add[0]=0;
newnode(rt,0,-1);
newnode(ch[rt][1],rt,-1);
build(Key_value,1,n,ch[rt][1]);
pushup(ch[rt][1]);
pushup(rt);
}
void rotate(int x,int p)
{
int y=pre[x];
pushdown(y);pushdown(x);
ch[y][!p]=ch[x][p];
pre[ch[x][p] ]=y;
if(pre[y])ch[pre[y] ][ch[pre[y] ][1]==y ]=x;
pre[x]=pre[y];
ch[x][p]=y;
pre[y]=x;
pushup(y);pushup(x);
}
void splay(int x,int goal)
{
pushdown(x);
while(pre[x]!=goal){
if(pre[pre[x] ]==goal){
pushdown(pre[x]);pushdown(x);
rotate(x,ch[pre[x]][0]==x);
}
else{
int y=pre[x];int z=pre[y];
pushdown(z);pushdown(y);pushdown(x);
int p=ch[pre[y] ][0]==y;
if(ch[y][p]==x )rotate(x,!p);
else rotate(y,p);
rotate(x,p);
}
}
if(goal==0)rt=x;
pushup(x);
}
int get_kth(int x,int k)
{
int i,j;
pushdown(x);
int t=sz[ch[x][0] ]+1;
if(t==k)return x;
if(t<k)return get_kth(ch[x][1],k-t);
return get_kth(ch[x][0],k);
}
void erase(int x)
{
if(x==0)return; //!!!
b[++tot2]=x;
erase(ch[x][0]);
erase(ch[x][1]);
}
void Add(int x,int y,int c)
{
splay(get_kth(rt,x),0);
splay(get_kth(rt,y+2),rt);
update_add(Key_value,c);
pushup(ch[rt][1]);
pushup(rt);
}
void Reverse(int x,int y)
{
splay(get_kth(rt,x),0);
splay(get_kth(rt,y+2),rt);
update_rev(Key_value);
pushup(ch[rt][1]);
pushup(rt);
}
void Insert(int x,int value)
{
int i,j;
splay(get_kth(rt,x+1),0);
splay(get_kth(rt,x+2),rt);
newnode(Key_value,ch[rt][1],value);
pushup(ch[rt][1]);
pushup(rt);
}
void Rotate(int x,int y,int c)
{
int len=y-x+1;
c=(c%len+len)%len;
if(c==0)return;
splay(get_kth(rt,y-c+1),0);
splay(get_kth(rt,y+2 ),rt);
int tmp=Key_value;
Key_value=0;
pushup(ch[rt][1]);
pushup(rt);
splay(get_kth(rt,x),0 );
splay(get_kth(rt,x+1),rt);
Key_value=tmp;
pre[tmp]=ch[rt][1];
pushup(ch[rt][1]);
pushup(rt);
}
void Delete(int pos,int tot)
{
splay(get_kth(rt,pos),0);
splay(get_kth(rt,pos+tot+1),rt);
erase(Key_value);
Key_value=0;
pushup(ch[rt][1]);
pushup(rt);
}
int Get_min(int x,int y)
{
splay(get_kth(rt,x),0);
splay(get_kth(rt,y+2),rt);
return mx[Key_value];
}
int main()
{
int m,i,j,pos,tot,c,d,e,f;
char s[10];
while(scanf("%d",&n)!=EOF)
{
for(i=1;i<=n;i++){
scanf("%d",&a[i]);
}
scanf("%d",&m);
init();
//debug();
for(i=1;i<=m;i++){
scanf("%s",s);
if(s[0]=='A'){
scanf("%d%d%d",&c,&d,&e);
Add(c,d,e);
}
if(s[0]=='R' && s[3]=='E'){
scanf("%d%d",&c,&d);
Reverse(c,d);
}
if(s[0]=='R' && s[3]=='O'){
scanf("%d%d%d",&c,&d,&e);
Rotate(c,d,e);
}
if(s[0]=='I'){
scanf("%d%d",&c,&d);
Insert(c,d);
}
if(s[0]=='D'){
scanf("%d",&c);
Delete(c,1);
}
if(s[0]=='M'){
scanf("%d%d",&c,&d);
printf("%d\n",Get_min(c,d));
//printf("1\n");
}
//debug();
}
}
return 0;
}
poj3580 SuperMemo (Splay+区间内向一个方向移动)的更多相关文章
- POJ3580 SuperMemo splay伸展树,区间操作
题意:实现一种数据结构,支持对一个数列的 6 种操作:第 x 个数到第 y 个数之间的数每个加 D:第 x 个数到第 y 个数之间全部数翻转:第 x 个数到第 y 个数之间的数,向后循环流动 c 次, ...
- 【BZOJ1895】Pku3580 supermemo Splay
[BZOJ1895]Pku3580 supermemo Description 给出一个初始序列fA1;A2;:::Ang,要求你编写程序支持如下操作: 1. ADDxyD:给子序列fAx:::Ayg ...
- 算法模板——splay区间反转 2
实现功能:同splay区间反转 1(基于BZOJ3223 文艺平衡树) 这次改用了一个全新的模板(HansBug:琢磨了我大半天啊有木有),大大简化了程序,同时对于splay的功能也有所完善 这里面没 ...
- P2596 [ZJOI2006]书架 && Splay 区间操作(三)
P2596 [ZJOI2006]书架 题目描述 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书, ...
- Splay(区间翻转)&树套树(Splay+线段树,90分)
study from: https://tiger0132.blog.luogu.org/slay-notes P3369 [模板]普通平衡树 #include <cstdio> #inc ...
- hdu 1890 Robotic Sort(splay 区间反转+删点)
题目链接:hdu 1890 Robotic Sort 题意: 给你n个数,每次找到第i小的数的位置,然后输出这个位置,然后将这个位置前面的数翻转一下,然后删除这个数,这样执行n次. 题解: 典型的sp ...
- splay模板三合一 luogu2042 [NOI2005]维护数列/bzoj1500 [NOI2005]维修数列 | poj3580 SuperMemo | luogu3391 【模板】文艺平衡树(Splay)
先是维修数列 题解看这里,但是我写的跑得很慢 #include <iostream> #include <cstdio> using namespace std; int n, ...
- BZOJ 2631: tree [LCT splay区间]
2631: tree Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 3854 Solved: 1292[Submit][Status][Discus ...
- 「BZOJ1251」序列终结者 (splay 区间操作)
题面: 1251: 序列终结者 Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 5367 Solved: 2323[Submit][Status][D ...
随机推荐
- jxl解析多个excel工作表-java代码
@Override public ResultBean txImportDqKpi(String filePath) { ResultBean rb = new ResultBean(); int s ...
- Promethues 之 Thanos
Promethues简介和原理 请看我之前写的 Prometheus简介,原理和安装 https://www.cnblogs.com/you-men/p/12839535.html 官方架构问题 官方 ...
- python列表字符串集合常用方法
1.1 列表常用方法 # 1. append 用于在列表末尾追加新的对象a = [1,2,3]a.append(4) # the result : [1,2,3,4]# 2. count方法统计某个 ...
- ctfhub技能树—信息泄露—备份文件下载—vim缓存
打开靶机 查看页面信息 在使用vim时会创建临时缓存文件,关闭vim时缓存文件则会被删除,当vim异常退出后,因为未处理缓存文件,导致可以通过缓存文件恢复原始文件内容 以 index.php 为例:第 ...
- 这难道不是.NET5 的bug? 在线求锤?
hello,最近在对一个使用.NET5项目的认证授权系统进行重构,对.NET 5的授权中间件的源码有些看法. 也希望同学们能帮我理解. 一个朴素的需求 这是一个api项目,默认所有的api都需要授权, ...
- 全网最全!彻底弄透Java处理GMT/UTC日期时间
目录 前言 本文提纲 版本约定 正文 Date类型实现 时区/偏移量TimeZone 设置默认时区 让人恼火的夏令时 Date时区无关性 读取字符串为Date类型 SimpleDateFormat格式 ...
- 扩展:Flash消息
扩展:Flash消息 flash存值之后只能取一次 from flask import Flask,render_template,flash,get_flashed_messages,session ...
- Linux定时任务crontab通俗易懂简单扼要地解析
1.安装crontab 在配置好yum源的情况下,直接执行如下命令即可: yum install crontab 2.查看当前环境上已经有的定时任务有哪些? 执行如下命令即可 crontab -l 如 ...
- (15)-Python3之--configparser模块
1.模块简介 configparser模块是python用来读取配置文件的模块,置文件的格式跟windows下的ini或conf配置文件相似,可以包含一个或多个节(section), 每个节可以有多个 ...
- C#高级编程第11版 - 第八章 索引
[1]8.1 引用方法 1.委托是指向方法的.NET地址变量. 2.委托是类型安全的类,定义了返回类型和参数类型.委托类不单单只包含一个方法引用,它也可以保存多个方法的引用. 3.Lambda表达式直 ...