博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Splay树(多操作)——POJ 3580 SuperMemo
阅读量:7041 次
发布时间:2019-06-28

本文共 6901 字,大约阅读时间需要 23 分钟。

相应POJ题目:

SuperMemo
Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 11309   Accepted: 3545
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:

  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 ...Ay} T 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 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

51 2 3 4 52ADD 2 4 1MIN 4 5

Sample Output

5

 

题意:

对n个数有6种操作:

1)增值:ADD x y D:区间 [x, y] 的全部值添加D

2)翻转:REVERSE x y:把区间 [x, y] 翻转

3)旋转:REVOLVE x y T:对区间 [x, y]顺时针(T > 0)或逆时针(T < 0)旋转T次

4)插入:INSERT x P:在A[x]后面插入P

5)删除:DELETE x:删除A[x]

6)最值:MIN x y:求区间 [x, y] 内的最小值

 

思路:

Splay树综合操作;须要注意的地方有:

1、Push_down()。Push_up()的写法。应该在什么地方调用

2、旋转操作的T能够是负数

3、旋转事实上就是把区间的后一段取下放到前面或着把前一段取下放到后面,不难想明确

 

#include 
#include
#include
#include
#include
#include
#include
#define MIN(x, y) ((x)<(y)?(x):(y))const int MAXN = 100100;using namespace std;typedef int Type;typedef struct TREE{ Type val, add, min_v; bool flag; TREE *fa, *l, *r; int sz; //以该结点为根的树的总结点数}Tree;inline void Swap(int &a, int &b){ int t = a; a = b; b = t;}class SplayTree{ public: SplayTree() { rt = NULL; inf = 1000000000; } void Push_down(Tree *T) { if(NULL == T) return; if(T->add){ if(T->l){ T->l->val += T->add; T->l->add += T->add; T->l->min_v += T->add; } if(T->r){ T->r->val += T->add; T->r->add += T->add; T->r->min_v += T->add; } T->add = 0; } if(T->flag){ tmp = T->l; T->l = T->r; T->r = tmp; if(T->l) T->l->flag ^= 1; if(T->r) T->r->flag ^= 1; T->flag = 0; } } void Push_up(Tree *T) { T->sz = (T->l ? T->l->sz : 0) + (T->r ? T->r->sz : 0) + 1; if(T->l && T->r) T->min_v = MIN(T->val, MIN(T->l->min_v, T->r->min_v)); else if(T->l) T->min_v = MIN(T->l->min_v, T->val); else if(T->r) T->min_v = MIN(T->r->min_v, T->val); else T->min_v = T->val; //切记!

} void NewNode(Tree *pre, Tree *&T, Type v) { T = (Tree *)malloc(sizeof(Tree)); T->val = T->min_v = v; T->add = 0; T->flag = 0; T->sz = 1; T->fa = pre; T->l = T->r = NULL; } void MakeTree(Tree *pre, Tree *&T, int x, int y) { if(x > y) return; int mid = ((x + y)>>1); NewNode(pre, T, c[mid]); MakeTree(T, T->l, x, mid - 1); MakeTree(T, T->r, mid + 1 , y); Push_up(T); } void Init(int n) { int i; for(i = 1; i <= n; i++) scanf("%d", c + i); NewNode(NULL, rt, -inf); NewNode(rt, rt->r, inf); rt->sz = 2; MakeTree(rt->r, rt->r->l, 1, n); Push_up(rt->r); Push_up(rt); } void R_rotate(Tree *x) { Tree *y = x->fa; Tree *z = y->fa; Tree *k = x->r; y->l = k; x->r = y; if(z){ if(y == z->l) z->l = x; else z->r = x; } if(k) k->fa = y; y->fa = x; x->fa = z; Push_up(y); } void L_rotate(Tree *x) { Tree *y = x->fa; Tree *z = y->fa; Tree *k = x->l; y->r = k; x->l = y; if(z){ if(y == z->r) z->r = x; else z->l = x; } if(k) k->fa = y; y->fa = x; x->fa = z; Push_up(y); } //寻找第x个数的结点 Tree *FindTag(int x) { x++; if(NULL == rt) return NULL; Tree *p; p = rt; Push_down(p); Type sum = (p->l ? p->l->sz : 0) + 1; while(sum != x) { if(sum < x){ p = p->r; x -= sum; } else p = p->l; if(NULL == p) break; Push_down(p); sum = (p->l ? p->l->sz : 0) + 1; } return p; } void Splay(Tree *X, Tree *&T) { Tree *p, *end; end = T->fa; while(X->fa != end) { p = X->fa; if(end == p->fa){ //p是根结点 if(X == p->l) R_rotate(X); else L_rotate(X); break; } //p不是根结点 if(X == p->l){ if(p == p->fa->l){ R_rotate(p); //LL R_rotate(X); //LL } else{ R_rotate(X); //RL L_rotate(X); } } else{ if(p == p->fa->r){ //RR L_rotate(p); L_rotate(X); } else{ //LR L_rotate(X); R_rotate(X); } } } T = X; Push_up(T); } void Get_interval(int x, int y) //把第x个数转到根,把第y个数转到根的右儿子 { tmp = FindTag(x); Splay(tmp, rt); tmp = FindTag(y); Splay(tmp, rt->r); } void Add(int x, int y, int d) { if(x > y) Swap(x, y); Get_interval(x - 1, y + 1); rt->r->l->add += d; rt->r->l->val += d; rt->r->l->min_v += d; Push_up(rt->r); Push_up(rt); } void Reverse(int x, int y) { if(x > y) Swap(x, y); Get_interval(x - 1, y + 1); rt->r->l->flag ^= 1; } void Revolve(int x, int y, int t) { if(x > y) Swap(x, y); t = t % (y - x + 1); //取模 if(t < 0) t += (y - x + 1); if(0 == t) return; Get_interval(y - t, y + 1); Tree *sub = rt->r->l; rt->r->l = NULL; Push_up(rt->r); Push_up(rt); Get_interval(x - 1, x); rt->r->l = sub; sub->fa = rt->r; Push_up(rt->r); Push_up(rt); } void Insert(int pos, int v) { Get_interval(pos, pos + 1); NewNode(rt->r, rt->r->l, v); Push_up(rt->r); Push_up(rt); } void Delete(int pos) { Get_interval(pos - 1, pos + 1); free(rt->r->l); rt->r->l = NULL; Push_up(rt->r); Push_up(rt); } void Min(int x, int y) { if(x > y) Swap(x, y); Get_interval(x - 1, y + 1); Push_down(rt->r->l); printf("%d\n", rt->r->l->min_v); } void Free() { FreeTree(rt); } void FreeTree(Tree *T) { if(NULL == T) return; FreeTree(T->l); FreeTree(T->r); free(T); } private: Type c[MAXN], inf; Tree *rt, *tmp; }; SplayTree spl; int main() { //freopen("in.txt","r",stdin); int n, m, x, y, z; char ord[10]; while(scanf("%d", &n) == 1) { spl.Init(n); scanf("%d", &m); while(m--) { scanf("%s", ord); if(!strcmp("ADD", ord)){ scanf("%d%d%d", &x, &y, &z); spl.Add(x, y, z); } if(!strcmp("REVERSE", ord)){ scanf("%d%d", &x, &y); spl.Reverse(x, y); } if(!strcmp("REVOLVE", ord)){ scanf("%d%d%d", &x, &y, &z); spl.Revolve(x, y, z); } if(!strcmp("INSERT", ord)){ scanf("%d%d", &x, &y); spl.Insert(x, y); } if(!strcmp("DELETE", ord)){ scanf("%d", &x); spl.Delete(x); } if(!strcmp("MIN", ord)){ scanf("%d%d", &x, &y); spl.Min(x, y); } } spl.Free(); } return 0; }

 

 

 

 

 

转载地址:http://ofxal.baihongyu.com/

你可能感兴趣的文章
SCVMM2012R2 服务模版系列(四)创建一个开箱即用的Web应用程序服务模版
查看>>
Visual Studio 2010 Ultimate敏捷功能特性(下)
查看>>
为 Neutron 准备物理基础设施(I) - 每天5分钟玩转 OpenStack(75)
查看>>
Android 中文API (91) —— GestureDetector
查看>>
CSS对字体单位的总结
查看>>
统计函数——汇总统计时间类数据
查看>>
精进不休 .NET 4.0 (6) - ADO.NET Data Services 1.5 新特性
查看>>
android 布局页面文件出错故障排除Exception raised during rendering: java.lang.System.arraycopy([CI[CII)V...
查看>>
熄灯问题
查看>>
引用类型参数,ref按引用传值
查看>>
基于Widnows Server 2003 SP2的系统需要新的系统准备工具
查看>>
C++ 制作 json 数据 并 传送给服务端(Server) 的 php
查看>>
如何从VS2003升级到VS2008
查看>>
Kernel内核的裁剪及移植(三)
查看>>
Oracle10g Bug 4612267 补丁安装备忘录
查看>>
我的Android开源项目:JNote
查看>>
跨线程操作UI
查看>>
关于Unity加载优化,你可能遇到这些问题
查看>>
在 Windows 7 和 Windows Server 2008 R2 上安装 Windows PowerShell 3.0
查看>>
专访IBM Power总经理 纵览Power 7新特性
查看>>