hdu4453-Looploop(伸展树)
题目有很多图,不好粘贴。。。。。
题意:给出N个数和K1,K2的值,最开始指针指向第一个数,有6种操作
add x : 给前K2个数都增加x
reverse : 翻转前K1个数
insert x : 在所指的数右边(顺时针)插入一个数
delete x : 删除指针所指的这个数,并且指针向右移(顺时针)
move x : x=1则指向向左移(逆时针),为2向右移(顺时针)
query : 输出指针所指的数
解析:这题涉及到插入删除,和给一段区间加值,线段树不能增加删除,链表的话又不能快速的给一段区间加数,所以只能用伸展树了。伸展树支持的操作很多,既有线段树的特性也有链表的特性。但是写起来复杂,所以一般题目如果能用常用的数据结构解决的就不要用伸展树了。我不具体介绍伸展树,自己下去多学学再看这题会容易许多。
源代码
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int INF=1e9+;
const int maxn=;
int A[maxn],cnt; //A数组保存数,cnt是节点标号,我是用数组模拟的
struct treap
{
treap* son[]; //左右儿子
int v,s,add,lazy; //v是值,s是大小,add是懒惰标记增加的值,lazy是懒惰标记是否需要翻转
treap(){ v=s=add=lazy=; son[]=son[]=NULL; }
treap(int nv);
int rk(){ return son[]->s+; } //排名,第几个数
int cmp(int k) //比较,如果相等返回-1,小于返回0,大于1
{
if(k==rk()) return -;
return k<rk()?:;
}
void pushup(){ s=son[]->s+son[]->s+; } //更新大小
void pushdown() //处理懒惰标记
{
if(lazy)
{
swap(son[],son[]);
son[]->lazy^=;
son[]->lazy^=;
lazy=;
}
if(add)
{
v+=add;
son[]->add+=add;
son[]->add+=add;
add=;
}
}
}null,tr[maxn];
treap::treap(int nv)
{
v=nv;
s=;
add=lazy=;
son[]=son[]=&null;
}
treap* NewNode(int x)
{
tr[cnt]=treap(x);
return tr+cnt++;
}
struct splaytree
{
int Size;
treap* root;
splaytree(){ Size=; root=&null; }
void Rotate(treap* &t,int d) //翻转操作
{
t->pushdown();
treap* p=t->son[d^];
p->pushdown();
t->son[d^]=p->son[d];
p->son[d]=t;
t->pushup();
t=p;
t->pushup();
}
void Splay(treap* &t,int k) //将第k大的节点伸展到根
{
t->pushdown();
int d=t->cmp(k);
if(d!=-)
{
if(d) Splay(t->son[d],k- t->rk());
else Splay(t->son[d],k);
Rotate(t,d^);
}
}
void Build(treap* &t,int le,int ri) //将N个数建成一棵树
{
if(le>ri) return;
int mid=(le+ri)/;
t=NewNode(A[mid]);
Build(t->son[],le,mid-);
Build(t->son[],mid+,ri);
t->pushup();
}
void Add(treap* &t,int k,int a) //加值
{
Splay(t,k);
t->v+=a;
t->son[]->add+=a;
}
void Reverse(treap* &t,int k) //翻转
{
Splay(t,k);
treap* p=t->son[];
t->son[]=&null;
t->pushup();
t->lazy=;
t->pushdown();
Splay(t,k);
t->son[]=p;
t->pushup();
}
void Insert(treap* &t,int x) //插入
{
Splay(t,);
treap* p=NewNode(x);
p->son[]=t->son[];
p->pushup();
t->son[]=p;
t->pushup();
Size++;
}
void Remove(treap* &t) 删除
{
Splay(t,);
treap* next=t->son[];
t=next;
t->pushdown();
Size--;
}
void Move(treap* &t,int x) //移动
{
if(x==)
{
Splay(t,Size);
treap* p=t->son[];
t->son[]=&null;
p->pushdown();
Splay(p,);
t->son[]=p;
t->pushup();
}
else
{
Splay(t,);
treap* p=t->son[];
t->son[]=&null;
p->pushdown();
Splay(p,Size-);
t->son[]=p;
t->pushup();
}
}
};
int N,M,K1,K2;
int main()
{
int Case=;
while(scanf("%d%d%d%d",&N,&M,&K1,&K2)!=EOF)
{
if(!N&&!M&&!K1&&!K2) break;
for(int i=;i<=N;i++) scanf("%d",&A[i]);
cnt=;
splaytree spt;
spt.Build(spt.root,,N);
spt.Size=N;
printf("Case #%d:\n",++Case);
while(M--)
{
char op[];
int x;
scanf("%s",op);
if(strcmp(op,"add")==)
{
scanf("%d",&x);
spt.Add(spt.root,K2,x);
}
else if(strcmp(op,"reverse")==) spt.Reverse(spt.root,K1);
else if(strcmp(op,"insert")==)
{
scanf("%d",&x);
spt.Insert(spt.root,x);
}
else if(strcmp(op,"delete")==) spt.Remove(spt.root);
else if(strcmp(op,"move")==)
{
scanf("%d",&x);
spt.Move(spt.root,x);
}
else
{
spt.Splay(spt.root,);
printf("%d\n",spt.root->v);
}
}
}
return ;
}
hdu4453-Looploop(伸展树)的更多相关文章
- Splay伸展树学习笔记
Splay伸展树 有篇Splay入门必看文章 —— CSDN链接 经典引文 空间效率:O(n) 时间效率:O(log n)插入.查找.删除 创造者:Daniel Sleator 和 Robert Ta ...
- 纸上谈兵:伸展树(splay tree)
作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 我们讨论过,树的搜索效率与树的深度有关.二叉搜索树的深度可能为n,这种情况下,每次 ...
- SplayTree伸展树的非递归实现(自底向上)
Splay Tree 是二叉查找树的一种,它与平衡二叉树.红黑树不同的是,Splay Tree从不强制地保持自身的平衡,每当查找到某个节点n的时候,在返回节点n的同时,Splay Tree会将节点n旋 ...
- 伸展树(一)之 图文解析 和 C语言的实现
概要 本章介绍伸展树.它和"二叉查找树"和"AVL树"一样,都是特殊的二叉树.在了解了"二叉查找树"和"AVL树"之后, ...
- 伸展树(二)之 C++的实现
概要 上一章介绍了伸展树的基本概念,并通过C语言实现了伸展树.本章是伸展树的C++实现,后续再给出Java版本.还是那句老话,它们的原理都一样,择其一了解即可. 目录1. 伸展树的介绍2. 伸展树的C ...
- 伸展树(三)之 Java的实现
概要 前面分别通过C和C++实现了伸展树,本章给出伸展树的Java版本.基本算法和原理都与前两章一样.1. 伸展树的介绍2. 伸展树的Java实现(完整源码)3. 伸展树的Java测试程序 转载请注明 ...
- hdu1890 伸展树(区间反转)
对于大神来说这题是水题.我搞这题花了快2天. 伸展树的优点有什么,就是树不管你怎么旋转序列是不会改变得,并且你要使区间反转,只要把第k大的点转到根结点,那么它的左子树就是要交换的区间[l,r),然后交 ...
- POJ 3580 (伸展树)
题目链接: http://poj.org/problem?id=3580 题目大意:对一个序列进行以下六种操作.输出MIN操作的结果. 解题思路: 六个操作,完美诠释了伸展树有多么吊.注意,默认使用L ...
- Splay 伸展树
废话不说,有篇论文可供参考:杨思雨:<伸展树的基本操作与应用> Splay的好处可以快速分裂和合并. ===============================14.07.26更新== ...
- UVa 11922 - Permutation Transformer 伸展树
第一棵伸展树,各种调试模板……TVT 对于 1 n 这种查询我处理的不太好,之前序列前后没有添加冗余节点,一直Runtime Error. 后来加上冗余节点之后又出了别的状况,因为多了 0 和 n+1 ...
随机推荐
- c++之命名空间namespace
1命名空间解决全局变量的冲突 main.h文件 #pragma once // data命名空间的名称 namespace data { ;//外部全局变量冲突 } main.cpp #include ...
- c语言sizeof与strlen的区别
#include <stdio.h> #include <stdlib.h> #include <string.h> //strlen与sizeof的区别 //st ...
- ubuntu14.04 + cocos2d-x-2.2.6 + eclipse发布android + Qt Creator4
先把需要的东西准备好,打开控制台,执行以下语句: sudo apt--jdk lib32z1 lib32ncurses5 lib32bz2- 接下来,准备好cocos2d-x-2.2.6和 andro ...
- (转)iOS7界面设计规范(11) - UI基础 - 图标与图形
不知别人如何,我自己来讲,平时很习惯很有动力去做的一些事,譬如博客吧,一旦生活中出现一些让自己很难受的状况,就很容易受到影响:像是,你平时所习惯的生活状态都是基于某种东西的,一旦这种东西崩塌,会影响到 ...
- [ES6] Generators
Example 1: function *topicList(){ yield "ES2015"; yield "Semi-colons: good or bad?&qu ...
- git config配置文件 (共有三个配置文件)
设置 git status的颜色. git config --global color.status auto 一.Git已经在你的系统中了,你会做一些事情来客户化你的Git环境.你只需要做这些设置一 ...
- javaweb中去除某个get方式的参数,并且返回路径
String requestURL = request.getRequestURL() + ""; // String queryString = request.getQuery ...
- 一张图看懂dex
最近在看dex文件格式,看的是飞虫大大的android软件安全与逆向分析一书,写的条理很清晰.相对于elf文件来说,dex文件格式简单了很多,但是提到某个字段,仍然难以想象其所处位置.所以一直想用思维 ...
- Android测试框架1(非原创)
1.继承AndroidTestCase :public class JunitTest3 extends AndroidTestCase {} 2.在AndroidManifest.xml清单文件中添 ...
- vi 快捷键【转】【weber整理必出精品】
光标的移动 命令 光标移动 h或^h 向左移一个字符 j或^j或^n 向下移一行 k或^p 向上移一行 l或空格 向右移一个字符 G 移到文件的最后一行 nG 移到文件的第n行 w 移到下一个字的开头 ...