题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3436

  树状数组做法<猛戳>

  Splay tree的经典题目,有删除和移动操作。首先要离散化各个点,而且对于没有区间还要缩点。对于Top操作,先把目标节点删除,然后移到最左端。Query操作,Splay(tar,0),然后直接访问size。对于Rank操作,通过size产找即可。注意,在每次更新后,都要把处理过的节点都要Splay(tar,0)才能保证复杂度为O(log n),因为这样才能方便下次的访问,因为这个TLE了一个下午+一个晚上。。。。Splay()操作太神了。。

 //STATUS:C++_AC_187MS_4196KB
#include <functional>
#include <algorithm>
#include <iostream>
//#include <ext/rope>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <numeric>
#include <cstring>
#include <cassert>
#include <cstdio>
#include <string>
#include <vector>
#include <bitset>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <list>
#include <set>
#include <map>
using namespace std;
//using namespace __gnu_cxx;
//define
#define pii pair<int,int>
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define PI acos(-1.0)
//typedef
typedef __int64 LL;
typedef unsigned __int64 ULL;
//const
const int N=;
const int INF=0x3f3f3f3f;
const int MOD=,STA=;
const LL LNF=1LL<<;
const double EPS=1e-;
const double OO=1e15;
const int dx[]={-,,,};
const int dy[]={,,,-};
const int day[]={,,,,,,,,,,,,};
//Daily Use ...
inline int sign(double x){return (x>EPS)-(x<-EPS);}
template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;}
template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}
template<class T> inline T lcm(T a,T b,T d){return a/d*b;}
template<class T> inline T Min(T a,T b){return a<b?a:b;}
template<class T> inline T Max(T a,T b){return a>b?a:b;}
template<class T> inline T Min(T a,T b,T c){return min(min(a, b),c);}
template<class T> inline T Max(T a,T b,T c){return max(max(a, b),c);}
template<class T> inline T Min(T a,T b,T c,T d){return min(min(a, b),min(c,d));}
template<class T> inline T Max(T a,T b,T c,T d){return max(max(a, b),max(c,d));}
//End #define Key_value ch[ch[root][1]][0]
int pre[N<<],ch[N<<][]; //分别表示父结点,键值,左右孩子(0为左孩子,1为右孩子),根结点,结点数量
int sz[N<<],st[N]; //子树规模,内存池
int root,tot,top; //根节点,根节点数量,内存池容量
//题目特定数据
int op[N],cnt[N<<],s[N<<],e[N<<];
int num[N],p[N];
int T,n,m,up;
//debug部分copy from hh
void Treaval(int x) {
if(x) {
Treaval(ch[x][]);
printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d\n",x,ch[x][],ch[x][],pre[x],sz[x]);
Treaval(ch[x][]);
}
}
void debug() {printf("%d\n",root);Treaval(root);}
//以上Debug
//新建一个结点
void NewNode(int &x,int fa,int k,int size)
{
// if(top)x=st[--top];
// else x=++tot;
x=k;
pre[x]=fa;
sz[x]=cnt[x]=size;
ch[x][]=ch[x][]=; //左右孩子为空
} inline void Push_Up(int x)
{
sz[x]=sz[ch[x][]]+sz[ch[x][]]+cnt[x];
}
//旋转,kind为1为右旋,kind为0为左旋
void Rotate(int x,int kind)
{
int y=pre[x],z=pre[y];
//类似SBT,要把其中一个分支先给父节点
ch[y][!kind]=ch[x][kind];
pre[ch[x][kind]]=y;
//如果父节点不是根结点,则要和父节点的父节点连接起来
if(z)ch[z][ch[z][]==y]=x;
pre[x]=z;
ch[x][kind]=y;
pre[y]=x;
Push_Up(y); //维护y结点,不要维护x节点,x节点会再次Push_Down,最后维护一下x节点即可
}
//Splay调整,将根为r的子树调整为goal
void Splay(int x,int goal)
{
int y,z,kind;
while(pre[x]!=goal){
//父节点即是目标位置,goal为0表示,父节点就是根结点
y=pre[x];
if(pre[y]==goal){
Rotate(x,ch[y][]==x);
}
else {
kind=ch[pre[y]][]==y;
//两个方向不同,则先左旋再右旋
if(ch[y][kind]==x){
Rotate(x,!kind);
Rotate(x,kind);
}
//两个方向相同,相同方向连续两次
else {
Rotate(y,kind);
Rotate(x,kind);
}
}
}
//更新根结点
Push_Up(x);
if(goal==)root=x;
} int Get_Min(int x)
{
while(ch[x][])x=ch[x][];
return x;
}
//建树,中间结点先建立,然后分别对区间两端在左右子树建立
void BuildTree(int &x,int l,int r,int fa)
{
if(l>r)return;
int mid=(l+r)>>;
NewNode(x,fa,mid,e[mid]-s[mid]+);
BuildTree(ch[x][],l,mid-,x);
BuildTree(ch[x][],mid+,r,x);
Push_Up(x);
} void Init()
{
root=tot=top=;
ch[][]=ch[][]=pre[]=sz[]=cnt[]=; int i,t,k;
char ss[];
p[]=,t=;
for(i=;i<=m;i++){
scanf("%s%d",ss,&num[i]);
op[i]=ss[]=='T'?:ss[]=='Q'?:;
if(op[i])p[t++]=num[i];
}
sort(p,p+t);
for(k=,i=;i<t;i++)
if(p[i]!=p[k])p[++k]=p[i];
for(i=,up=;i<=k;i++){
if(p[i]-p[i-]>){
s[++up]=p[i-]+;
e[up]=p[i]-;
}
s[++up]=p[i];
e[up]=p[i];
}
if(e[up]!=n){
++up;
s[up]=e[up-]+;
e[up]=n;
}
BuildTree(root,,up,);
}
//删除编号为x的节点
void Delete(int x)
{
int y=pre[x],s;
if(sz[x]==cnt[x]){
ch[y][ch[y][]==x]=;
s=y;
}
else if(ch[x][]== || ch[x][]==){
s=ch[x][]?ch[x][]:ch[x][];
if(y)ch[y][ch[y][]==x]=s;
pre[s]=y;
}
else {
s=Get_Min(ch[x][]);
Splay(s,x);
if(ch[x][]){
ch[s][]=ch[x][];
pre[ch[x][]]=s;
}
pre[s]=y;
if(y)ch[y][ch[y][]==x]=s;
}
if(y==)root=s;
Splay(s,);
} void Top(int tar)
{
if(sz[root]==cnt[root])return;
Delete(tar);
int x=Get_Min(root);
ch[x][]=tar;
pre[tar]=x;
sz[tar]=cnt[tar];
ch[tar][]=ch[tar][]=;
Splay(tar,);
} int Query(int tar)
{
Splay(tar,);
return sz[ch[root][]]+cnt[tar];
} int Rank(int k)
{
int x=root;
while(){
if(k>sz[ch[x][]] && k<=sz[ch[x][]]+cnt[x]){
k-=sz[ch[x][]];
break;
}
else if(k<=sz[ch[x][]])
x=ch[x][];
else {
k-=sz[ch[x][]]+cnt[x];
x=ch[x][];
}
}
return s[x]+k-;
} int binary(int l,int r,int tar)
{
int mid;
while(l<r){
mid=(l+r)>>;
if(e[mid]<tar)l=mid+;
else if(s[mid]>tar)r=mid;
else return mid;
}
return -;
} int main()
{
// freopen("in.txt","r",stdin);
int i,j,ca=,tar;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
Init();
printf("Case %d:\n",ca++);
for(i=;i<=m;i++){
if(op[i]){
tar=binary(,up+,num[i]);
if(op[i]==)Top(tar);
else printf("%d\n",Query(tar));
}
else printf("%d\n",Rank(num[i]));
}
}
return ;
}

HDU-3436 Queue-jumpers 树状数组 | Splay tree删除,移动的更多相关文章

  1. 洛谷P3960 列队 NOIp2017 线段树/树状数组/splay

    正解:动态开点线段树 解题报告: 传送门! 因为最近学主席树的时候顺便get到了动态开点线段树?刚好想起来很久很久以前就想做结果一直麻油做的这题,,,所以就做下好了QAQ 然后说下,这题有很多种方法, ...

  2. HDU - 1541 Stars 【树状数组】

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1541 题意 求每个等级的星星有多少个 当前这个星星的左下角 有多少个 星星 它的等级就是多少 和它同一 ...

  3. HDU 3333 | Codeforces 703D 树状数组、离散化

    HDU 3333:http://acm.hdu.edu.cn/showproblem.php?pid=3333 这两个题是类似的,都是离线处理查询,对每次查询的区间的右端点进行排序.这里我们需要离散化 ...

  4. hdu-5493 Queue(二分+树状数组)

    题目链接: Queue Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total ...

  5. hdu 4267 多维树状数组

    题意:有一个序列 "1 a b k c" means adding c to each of Ai which satisfies a <= i <= b and (i ...

  6. HDU 4777 Rabbit Kingdom 树状数组

    分析:找到每一个点的左边离他最近的不互质数,记录下标(L数组),右边一样如此(R数组),预处理 这个过程需要分解质因数O(n*sqrt(n)) 然后离线,按照区间右端点排序 然后扫一遍,对于当前拍好顺 ...

  7. HDU 6348 序列计数 (树状数组 + DP)

    序列计数 Time Limit: 4500/4000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Subm ...

  8. HDU 4325 Flowers(树状数组+离散化)

    http://acm.hdu.edu.cn/showproblem.php?pid=4325 题意:给出n个区间和m个询问,每个询问为一个x,问有多少个区间包含了x. 思路: 因为数据量比较多,所以需 ...

  9. hdu 5775 Bubble Sort 树状数组

    Bubble Sort 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5775 Description P is a permutation of t ...

随机推荐

  1. CF 136A Presents

    http://codeforces.com/problemset/problem/136/A 题意 :就是输入很多数字,第 i 个数字 pi 代表着第 i 个人的礼物给了第 pi 个人,而让你输出的数 ...

  2. 转:tar 常用命令

    tar在linux上是常用的打包.压缩.加压缩工具,他的参数很多,折里仅仅列举常用的压缩与解压缩参数 参数: -c :create 建立压缩档案的参数: -x : 解压缩压缩档案的参数: -z : 是 ...

  3. 15个必知的Android开发者选项

    Android开发者选项,看起来很简单的事情,其实很多同学对它了解得不够,Google用心良苦得为我们设计了这么多小开关都是有它的作用的,今天也花了点时间,过了一遍全部的30多个开关,从中整理出15个 ...

  4. windows下配置环境变量时,在cmd窗口执行配置的命令时无效的原因

    一个原因肯定就是配置错误,这个就要自己仔细去检查了,如果确信配置正确,可能是你的cmd窗口在环境变量配置之前就打开的,在配置好环境变量之后,在cmd窗口执行命令是看不到效果的,可以关掉cmd窗口再重新 ...

  5. redolog 大小的实验

    前言:近日因工作需要,测试postgresql和MySQL在oltp对比测试,因结果差异太多(MySQL测试结果比较差,相同环境),寻求大神帮助,有幸得叶大师和姜大师指点,指出my.cnf配置文件in ...

  6. (转)Redis与Memcached的区别

    如果简单地比较Redis与Memcached的区别,大多数都会得到以下观点: 1 Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,hash等数据结构的存储. 2 Redis支持 ...

  7. Linux配置vpn

    配置如下

  8. Eclipse下Preferences解析

    General列表下: Keys设置快捷键 Appearance->Colors and Fonts->Text-Font设置字体和大小 Appearance->Startup an ...

  9. EXCEL VB

    全面控制 Excel首先创建 Excel 对象,使用ComObj:Dim ExcelID as Excel.ApplicationSet ExcelID as new Excel.Applicatio ...

  10. ↗☻【HTML5秘籍 #BOOK#】第1章 HTML5简介

    <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8& ...