【算法】splay

【题解】

splay维护序列,用权值(离散化)作为编号。每次找第i小的话直接找对应编号splay即可。

但是这样splay没有下传翻转标记?直接暴力找到路径然后从根到改结点pushdown。暴力出奇迹!

如果没有find就直接splay,一定记得更新设置splay为传值调用并且在过程中更新地址才能更新root。

#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
using namespace std;
const int maxn=;
int f[maxn],t[maxn][],s[maxn],first[maxn],second[maxn],ord[maxn],a[maxn],node[maxn],n,root,ans[maxn];
bool g[maxn];
int read()
{
char c;int s=;
while(!isdigit(c=getchar()));
do{s=s*+c-'';}while(isdigit(c=getchar()));
return s;
}
bool cmp(int x,int y)
{return (first[x]<first[y])||(first[x]==first[y]&&second[x]<second[y]);}
void pushdown(int x)
{
if(g[x])
{
g[t[x][]]^=;g[t[x][]]^=;
swap(t[x][],t[x][]);
g[x]=;
}
}
void count(int x)
{s[x]=s[t[x][]]++s[t[x][]];}
void rotate(int x)
{
int k=x==t[f[x]][];
int y=f[x];
t[y][k]=t[x][!k];f[t[x][!k]]=y;
if(f[y])t[f[y]][y==t[f[y]][]]=x;f[x]=f[y];f[y]=x;
t[x][!k]=y;s[x]=s[y];//因为已经pushdown了所以不用传翻转标记
count(y);
}
void splay(int &r,int x)
{
int tot=;
for(int i=x;i!=r;i=f[i])node[++tot]=i;node[++tot]=r;
for(int i=tot;i>=;i--)pushdown(node[i]);
for(int fa=f[r];f[x]!=fa;)
{
if(f[f[x]]==fa){rotate(x);break;}//return之前要记得传参……所以还是break好……
int X=x==t[f[x]][],Y=f[x]==t[f[f[x]]][];
if(X^Y)rotate(x),rotate(x);
else rotate(f[x]),rotate(x);
}
r=x;
}
void find(int &r,int k)
{
for(int x=r;x;)
{
pushdown(x);
if(k<=s[t[x][]]){x=t[x][];continue;}
if(k==s[t[x][]]+){splay(r,x);return;}
k-=s[t[x][]]+;x=t[x][];
}
}
void build(int fa,int &x,int l,int r)
{
if(l>r)return;
int mid=(l+r)>>;
x=a[mid];f[x]=fa;g[x]=;s[x]=;
build(x,t[x][],l,mid-);
build(x,t[x][],mid+,r);
count(x);
}
//void writes()
//{
// printf("------------------------------------------\n");
// for(int i=0;i<=n+2;i++)printf("[%d]t1=%d t2=%d fa=%d g=%d s=%d\n",i,t[i][0],t[i][1],f[i],g[i],s[i]);
// printf("------------------------------------------\n");
//}
int main()
{
n=read();
for(int i=;i<=n;i++)
{
first[i]=read();
second[i]=i;
ord[i]=i;
}
sort(ord+,ord+n+,cmp);
for(int i=;i<=n;i++)a[ord[i]]=i;
a[]=n+;a[n+]=n+;
build(,root,,n+);
for(int i=;i<=n;i++)
{
splay(root,i);
int p=s[t[root][]];
ans[i]=p;
find(root,i);
find(t[root][],p-i+);
g[t[t[root][]][]]^=;
}
for(int i=;i<n;i++)printf("%d ",ans[i]);
printf("%d",ans[n]);
return ;
}

update:现在已改用fhq-treap代替splay。

【BZOJ】1552/3506 [Cerc2007]robotic sort的更多相关文章

  1. BZOJ 1552/1506 [Cerc2007]robotic sort

    AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=1552 [分析] 这题哇!又有翻转操作...每次要输出第几个?是吧... 所以又要用Spla ...

  2. 洛谷 P4402 BZOJ1552 / 3506 [Cerc2007]robotic sort 机械排序

    FHQ_Treap 太神辣 蒟蒻初学FHQ_Treap,于是来到了这道略显板子的题目 因为Treap既满足BST的性质,又满足Heap的性质,所以,对于这道题目,我们可以将以往随机出的额外权值转化为每 ...

  3. BZOJ1552/3506 [Cerc2007]robotic sort

    Splay 与之前不同的是如果你仅仅是翻转左右区间的话可以在find里面做因为对他有影响的子树在做之前一定在他的上面从上到下搜索的过程可以把rever做了. 但这道题要求我们输出转换之前的,因此不能保 ...

  4. 【BZOJ】【1552】【Cerc2007】robotic sort / 【3506】【CQOI2014】排序机械臂

    Splay 离散化+Splay维护序列…… 好吧主要说一下我做这道题遇到的几个错误点: 1.离散化 2.由于找到的这个数的位置一定是大于等于 i 的,所以其实在把它splay到根以后,i 结点只能sp ...

  5. 【bzoj1552/3506】[Cerc2007]robotic sort splay翻转,区间最值

    [bzoj1552/3506][Cerc2007]robotic sort Description Input 输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000. ...

  6. BZOJ 1552: [Cerc2007]robotic sort( splay )

    kpm大神说可以用块状链表写...但是我不会...写了个splay.... 先离散化 , 然后splay结点加个min维护最小值 , 就可以了... ( ps BZOJ 3506 题意一样 , 双倍经 ...

  7. 【BZOJ1552】[Cerc2007]robotic sort Splay

    [BZOJ1552][Cerc2007]robotic sort Description Input 输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000.第二行为N ...

  8. bzoj 1552: [Cerc2007]robotic sort

    1552: [Cerc2007]robotic sort Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1198  Solved: 457[Submit] ...

  9. 【BZOJ】3052: [wc2013]糖果公园

    http://www.lydsy.com/JudgeOnline/problem.php?id=3052 题意:n个带颜色的点(m种),q次询问,每次询问x到y的路径上sum{w[次数]*v[颜色]} ...

随机推荐

  1. Java微笔记(3)

    Java 中的 static 使用之静态变量 Java 中被 static 修饰的成员称为静态成员或类成员. 它属于整个类所有,而不是某个对象所有,即被类的所有对象所共享. 静态成员可以使用类名直接访 ...

  2. [经典贪心算法]Prim算法

    最小生成树的Prim算法也是贪心算法的一大经典应用.Prim算法的特点是时刻维护一棵树,算法不断加边,加的过程始终是一棵树. Prim算法过程: 一条边一条边地加, 维护一棵树. 初始 E = {}空 ...

  3. 《剑指offer》---跳台阶问题

    本文算法使用python3实现 1. 问题1 1.1 题目描述:   一只青蛙一次可以跳上1级台阶,也可以跳上2级.求该青蛙跳上一个n级的台阶总共有多少种跳法.   时间限制:1s:空间限制:3276 ...

  4. 往Matlab中添加工具包

    使用Matlab过程中,常常会缺少一些函数包导致无法运行,会显示未定义函数. 假如我要用sigshift( ) 这个移位函数,但Matlab中没有,就会提示错误:未定义函数或变量 'sigshift' ...

  5. css那些事儿4 背景图像

    background:背景颜色,图像,平铺方式,大小,位置 能够显示背景区域即为盒子模型的填充和内容部分,其中背景图像将会覆盖背景颜色.常见的水平或垂直渐变颜色背景通常使用水平或垂直渐变的背景图像在水 ...

  6. 微信小程序wx.pageScrollTo的替代方案

    wx.pageScrollTo这个微信小程序的api功能如下: 简而言之就是实现页面滚动的.但是在实际应用当中显得有些鸡肋,为啥呢?使用中有明显页面有明显的抖动,这无疑是极不好的用户体验.我用的华为6 ...

  7. node 第一天

    在开发的过程中,几乎不可能一次性就能写出毫无破绽的程序,断点调试代码是一个普遍的需求. 作为前端开发工程师,以往我们开发的JavaScript程序都运行在浏览器端,利用Chrome提供的开发者工具就可 ...

  8. [转]Windows 7 蓝屏后获取 MEMORY.DMP 文件及注意事项

    转自:http://hi.baidu.com/guicomeon/item/d6753a177fc76f0f8fbde46a 系统默认会在 C:\Windows 目录下创建 MEMORY.DMP 文件 ...

  9. [剑指Offer] 60.把二叉树打印成多行

    题目描述 从上到下按层打印二叉树,同一层结点从左至右输出.每一层输出一行. [思路]使用队列实现二叉树的层次遍历. /* struct TreeNode { int val; struct TreeN ...

  10. iOS开发UI篇—transframe属性(形变)

    iOS开发UI篇—transframe属性(形变) 1. transform属性 在OC中,通过transform属性可以修改对象的平移.缩放比例和旋转角度 常用的创建transform结构体方法分两 ...