HDU-3436 Queue-jumpers 树状数组 | Splay tree删除,移动
题目链接: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删除,移动的更多相关文章
- 洛谷P3960 列队 NOIp2017 线段树/树状数组/splay
正解:动态开点线段树 解题报告: 传送门! 因为最近学主席树的时候顺便get到了动态开点线段树?刚好想起来很久很久以前就想做结果一直麻油做的这题,,,所以就做下好了QAQ 然后说下,这题有很多种方法, ...
- HDU - 1541 Stars 【树状数组】
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1541 题意 求每个等级的星星有多少个 当前这个星星的左下角 有多少个 星星 它的等级就是多少 和它同一 ...
- HDU 3333 | Codeforces 703D 树状数组、离散化
HDU 3333:http://acm.hdu.edu.cn/showproblem.php?pid=3333 这两个题是类似的,都是离线处理查询,对每次查询的区间的右端点进行排序.这里我们需要离散化 ...
- hdu-5493 Queue(二分+树状数组)
题目链接: Queue Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total ...
- hdu 4267 多维树状数组
题意:有一个序列 "1 a b k c" means adding c to each of Ai which satisfies a <= i <= b and (i ...
- HDU 4777 Rabbit Kingdom 树状数组
分析:找到每一个点的左边离他最近的不互质数,记录下标(L数组),右边一样如此(R数组),预处理 这个过程需要分解质因数O(n*sqrt(n)) 然后离线,按照区间右端点排序 然后扫一遍,对于当前拍好顺 ...
- HDU 6348 序列计数 (树状数组 + DP)
序列计数 Time Limit: 4500/4000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total Subm ...
- HDU 4325 Flowers(树状数组+离散化)
http://acm.hdu.edu.cn/showproblem.php?pid=4325 题意:给出n个区间和m个询问,每个询问为一个x,问有多少个区间包含了x. 思路: 因为数据量比较多,所以需 ...
- hdu 5775 Bubble Sort 树状数组
Bubble Sort 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5775 Description P is a permutation of t ...
随机推荐
- 220. Contains Duplicate III
题目: Given an array of integers, find out whether there are two distinct indices i and j in the array ...
- POJ1068——Parencodings
Parencodings Description Let S = s1 s2...s2n be a well-formed string of parentheses. S can be encode ...
- Servlet 下载文件
这几天有点懒散,还好没有忘记看书,上周去了国家图书馆翻阅了一些和Java相关的书籍,其实这些书都是自己以前看过或者听过,按理来说,不应该看自己已经看过的书籍,应该找一些最新的书籍去看,但是每次走到书架 ...
- ARM7ldr指令与ldr伪指令
ldr伪指令的第二个操作数之前有个=,意思是第一个操作书 = 第二个操作数,相当明了 核心就在于对于用.word指令在.text段里另外定义一段内存,用ldr r0,[pc + x(可以算出.text ...
- 基于Android Studio搭建Android应用开发环境
备注:电脑是windows xp系统 1. 安装JDK和环境变量设置 JDK是java development kit,Java JDK下载地址 http://www.oracle.com/t ...
- HashMap和Hashtable的区别(1)
导读: 1 HashMap不是线程安全的 hastmap实现了map接口,是将键映射到值的对象,其中键和值都是对象,并且不能包含重复键,但可以包含重复值.HashMap允许null key和null ...
- Java中的volatile
关于volatile 在JVM 1.2之前,Java的内存模型实现总是从主存读取变量,是不需要进行特别的注意的.而随着JVM的成熟和优化,现在在多线程环境下 volatile关键字的使用变得非常重要. ...
- PostgreSql与sqlserver对比杂记
PostgreSql与MSSqlServer区别 增删查改没有语法一样. 排序Group Having 聚集函数使用一样 联结查询 ON 子句是最常见的连接条件的类型:它接收一个和 WHERE 子句相 ...
- C++ 学习资料搜寻与学习(第一期)(未完待续)
一.图形图像类 [Visual C++]vs2008/2005正确打开vs2010所创建项目的几种方法 jlins 2012-04-12 14:38 [Visual C++]关于无法打开包括文件:“S ...
- Java操作Hbase进行建表、删表以及对数据进行增删改查,条件查询
1.搭建环境 新建JAVA项目,添加的包有: 有关Hadoop的hadoop-core-0.20.204.0.jar 有关Hbase的hbase-0.90.4.jar.hbase-0.90.4-tes ...