【BZOJ3678】wangxz与OJ Splay
【BZOJ3678】wangxz与OJ
Description
某天,wangxz神犇来到了一个信息学在线评测系统(Online Judge)。由于他是一位哲♂学的神犇,所以他不打算做题。他发现这些题
目呈线性排列,被标记为1~n号,每道题都有一个难度值(可以<=0)。他决定与这些题目玩♂耍。
1、他可以在某个位置插♂入一些难度值特定的题目。
2、他可以吃♂掉(删除)一段题目。
3、他可以查询某个位置的题目的难度值。
维护一个初始有n个元素的序列(标记为1~n号元素),支持以下操作:
0 p a b (0<=p<=当前序列元素个数) (a<=b) 在p位置和p+1位置之间插入整数:a,a+1,a+2,...,b-1,b。若p为0,插在序列最前面;
1 a b (1<=a<=b<=当前序列元素个数) 删除a,a+1,a+2,...,b-1,b位置的元素;
2 p (1<=p<=当前序列元素个数) 查询p位置的元素。
Input
输入第一行包括两个正整数n(1<=n<=20000),m(1<=m<=20000),代表初始序列元素个数和操作个数。
接下来n个整数,为初始序列元素。
接下来m行,每行第一个为整数sym,
若sym=0,接下来有一个非负整数p,两个整数a,b;
若sym=1,接下来有两个正整数a,b;
若sym=2,接下来有一个正整数p;
p、x、y的含义及范围见题目描述。
在任何情况下,保证序列中的元素总数不超过100000。
保证题目涉及的所有数在int内。
Output
对每个sym=2,输出一行,包括一个整数,代表询问位置的元素。
Sample Input
1 2 3 4 5
0 2 1 4
1 3 8
2 2
Sample Output
题解:容易想到用Splay,我们的Splay的每个节点处维护的不是一个点,而是连续的一段数[a,b]。我们需要实现一个split操作:如果我们想将c和c+1分开,那么我们先找到c所在的节点,将它的后继提上来,并在二者之间新建一个点,将当前节点变成[a,c],并将新点变成[c+1,b]即可。特别地,如果c==b,则不用操作。
其余的操作就很容易了。
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
struct node
{
int ch[2],a,b,fa,siz;
}s[200010];
int n,m,tot,rt;
inline void pushup(int x)
{
s[x].siz=s[s[x].ch[0]].siz+s[s[x].ch[1]].siz+s[x].b-s[x].a+1;
}
int build(int l,int r)
{
if(l>r) return 0;
int x=(l+r)>>1;
s[x].ch[0]=build(l,x-1),s[x].ch[1]=build(x+1,r);
if(s[x].ch[0]) s[s[x].ch[0]].fa=x;
if(s[x].ch[1]) s[s[x].ch[1]].fa=x;
pushup(x);
return x;
}
inline void rotate(int x,int &k)
{
int y=s[x].fa,z=s[y].fa,d=(x==s[y].ch[1]);
if(z) s[z].ch[y==s[z].ch[1]]=x;
else if(y==k) k=x;
s[x].fa=z,s[y].fa=x,s[y].ch[d]=s[x].ch[d^1];
if(s[x].ch[d^1]) s[s[x].ch[d^1]].fa=y;
s[x].ch[d^1]=y;
pushup(y),pushup(x);
}
inline void splay(int x,int &k)
{
while(x!=k)
{
int y=s[x].fa,z=s[y].fa;
if(y!=k)
{
if((x==s[y].ch[0])^(y==s[z].ch[0])) rotate(x,k);
else rotate(y,k);
}
rotate(x,k);
}
}
int find(int x,int y)
{
if(!x) return 0;
if(y>s[s[x].ch[0]].siz&&y<=s[s[x].ch[0]].siz+s[x].b-s[x].a+1) return x;
if(s[s[x].ch[0]].siz>=y) return find(s[x].ch[0],y);
return find(s[x].ch[1],y-s[s[x].ch[0]].siz-s[x].b+s[x].a-1);
}
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+(gc^'0'),gc=getchar();
return ret*f;
}
inline void split(int y)
{
int x=find(rt,y+1);
splay(x,rt),splay(find(rt,s[s[x].ch[0]].siz+s[x].b-s[x].a+2),s[x].ch[1]);
if(s[s[x].ch[0]].siz+s[x].b-s[x].a==y) return ;
int z=++tot;
s[z].b=s[x].b,s[x].b=s[x].a+y-s[s[x].ch[0]].siz,s[z].a=s[x].b+1;
s[z].fa=s[x].ch[1],s[s[x].ch[1]].ch[0]=z;
pushup(z),pushup(s[x].ch[1]),pushup(x);
rotate(z,s[x].ch[1]);
}
int main()
{
n=rd(),m=rd();
int i,x,y,a,b,op;
for(i=1;i<=n;i++) s[i+1].a=s[i+1].b=rd();
rt=build(1,n+2),tot=n+2;
for(i=1;i<=m;i++)
{
op=rd();
if(op==0)
{
a=rd(),split(a);
x=++tot,s[x].a=rd(),s[x].b=rd(),s[x].fa=s[rt].ch[1],s[s[rt].ch[1]].ch[0]=x;
pushup(x),pushup(s[rt].ch[1]),pushup(rt);
}
if(op==1)
{
a=rd(),b=rd(),split(a-1),split(b);
x=find(rt,a),splay(x,rt),y=find(rt,b+2),splay(y,s[x].ch[1]);
s[y].ch[0]=0;
pushup(y),pushup(x);
}
if(op==2)
{
a=rd(),x=find(rt,a+1),splay(x,rt);
printf("%d\n",a-s[s[x].ch[0]].siz+s[x].a);
}
}
return 0;
}//5 3 1 2 3 4 5 0 2 1 4 1 3 8 2 2
【BZOJ3678】wangxz与OJ Splay的更多相关文章
- BZOJ3678: wangxz与OJ
splay缩点. #include<bits/stdc++.h> #define L(t) (t)->c[0] #define R(t) (t)->c[1] #define F ...
- BZOJ3678 wangxz与OJ (平衡树 无旋treap)
题面 维护一个序列,支持以下操作: 1.在某个位置插入一段值连续的数. 2.删除在当前序列位置连续的一段数. 3.查询某个位置的数是多少. 题解 显然平衡树,一个点维护一段值连续的数,如果插入或者删除 ...
- bzoj 3678 wangxz与OJ
3678: wangxz与OJ Time Limit: 10 Sec Memory Limit: 128 MBhttp://www.lydsy.com/JudgeOnline/problem.php ...
- 【bzoj3678】wangxz与OJ
Portal -- > bzoj 3678 Solution 这题==真实智力康复qwq 然而众多神犇都说是10min写完的题我..可能写了近1h吧==深深感受到自己的弱小qwq (丢上来是因为 ...
- 【BZOJ3678】Wangxz和OJ
题意: 不想讲 题解: Rope真香! 正解是Splay缩点,访问时再拆成一个序列 代码: //STL dafa good! #include<algorithm> #include< ...
- BZOJ 3595: [Scoi2014]方伯伯的Oj Splay + 动态裂点 + 卡常
Description 方伯伯正在做他的Oj.现在他在处理Oj上的用户排名问题. Oj上注册了n个用户,编号为1-”,一开始他们按照编号排名.方伯伯会按照心情对这些用户做以下四种操作,修改用户的排名和 ...
- luogu P3285 [SCOI2014]方伯伯的OJ splay 线段树
LINK:方伯伯的OJ 一道稍有质量的线段树题目.不写LCT splay这辈子是不会单独写的 真的! 喜闻乐见的是 题目迷惑选手 \(op==1\) 查改用户在序列中的位置 题目压根没说位置啊 只有排 ...
- [BZOJ3678]wangxz与OJ-[Splay一类的平衡树]
Description 传送门 Solution 直接splay搞定吧..似乎非旋treap也ok? 我已经菜到模板题都写不出来了qaq Code #include<iostream> # ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
随机推荐
- POJ 1523 SPF 割点与桥的推断算法-Tarjan
题目链接: POJ1523 题意: 问一个连通的网络中有多少个关节点,这些关节点分别能把网络分成几部分 题解: Tarjan 算法模板题 顺序遍历整个图,能够得到一棵生成树: 树边:可理解为在DFS过 ...
- Spring - BeanFactory 新旧工厂差异
在将要被加入到spring容器中的service中,添加static静态代码块(加载类时被调用),用于判断spring中新旧bean工厂的加载性质. package com.witwicky.serv ...
- 隐藏的Swiper显示后无法获取正确的宽度和高度
今天在使用swiper的时候,元素默认是显示的时候没毛病,但是默认是隐藏的状态,再显示的时候发现滑动的时候宽度计算有误,如下图所示: 正确的显示如下: 隐藏的元素再次显示如下: 宽度计算有误 解决方案 ...
- Qt Q_DECLARE_METATYPE说明——让自定义的类型设置到QVariant
在使用Qt进行应用程序开发时,经常要自定义数据类型,而且在需要的时候还要把这些数据放到QVariant中去.因为QVariant是一个接受绝大部分类型的数据类型.为了达到这个目的,就必须使用Q_DEC ...
- 《FPGA全程进阶---实战演练》第三章之PCB设计之去耦电容
1.关于去耦电容为何需要就近摆放? 大多数资料有提到过,去耦电容就近放置,是从减小回路电感的角度去谈及摆放问题,其实还有一个原则就是去耦半径的问题,如果电容离着芯片位置较远,超过去耦半径,会起不到去耦 ...
- android 内存管理机制、异常、垃圾回收
当 Android 应用程序退出时,并不清理其所占用的内存,Linux 内核进程也相应的继续存在,所谓“退出但不关闭”.从而使得用户调用程序时能够在第一时间得到响应. 当系统内存不足时,系统将激活内存 ...
- ScreenPointToRay - 近视口到屏幕的射线
正如题目所说,ScreenPointToRay可以计算从Camera的近视口nearClip向前发射一条射线到屏幕上的点的坐标. 函数原型为: public Ray ScreenPointToRay( ...
- url传参错误的痛
今天用一下方法给后台传参数: var url = 'patrolpoint!totalHistoryPage.action' + '?patrolPoint.batchOnTime=' ...
- pushlet 之 Pushlet使用手把手实例
Pushlet(一种comet 架构的实现)是基于Servlet 机制,数据从server端的Java 对象直接推送(push) 到客户端浏览器的(动态)HTML 页面,而无需任何Java app ...
- ros-indigo-desktop-full安装到ubuntu14.04
一.安装ros(原创博文,转载请标明出处-周学伟http://www.cnblogs.com/zxouxuewei/) 1.配置ubuntu的软件仓库.(可以不用进行配置). 配置你的 Ubuntu ...