[NOI模拟题7T2 Sort]
2012-02-27 23:01
148 查看
[关键字]:数据结构 Splay
[题目大意] :有一个数字序列,按照如下顺序进行排序:在第i次交换时找到第i小的数字所在的位置k然后将[i,k]区间反转。问第i次反转前第i小的数字所在的位置。
//==============================================================================================
[分析]:既要支持反转操作又要快速查找的数据结构一定是——伸展树!但一开始我没想好怎么用,为了维护序列的顺序必须以原序列下标为关键字建立Splay,但是这样就无法快速查找第i小的数的位置,然后我就冥思苦想了一天发现自己二了……可以这样:一原序列下标为关键字建立Splay但是树的节点编号为此位置上的值是第几小。这样,每次就可以维护好Splay然后直接就可求出第i小的值的位置:它所在的节点的左子树大小+1,因为它将被置于前面不会被再次反转,为了方便可以将这个点删掉,没必要真删,只要将它所在子树大小-1,它的dat变成0。注意的是更新的顺序,自底向上更新子树大小时要先更新下面再更新上面,而传递反转的bool标记要先更新上面再更新下面。
[代码]:
View Code
[题目大意] :有一个数字序列,按照如下顺序进行排序:在第i次交换时找到第i小的数字所在的位置k然后将[i,k]区间反转。问第i次反转前第i小的数字所在的位置。
//==============================================================================================
[分析]:既要支持反转操作又要快速查找的数据结构一定是——伸展树!但一开始我没想好怎么用,为了维护序列的顺序必须以原序列下标为关键字建立Splay,但是这样就无法快速查找第i小的数的位置,然后我就冥思苦想了一天发现自己二了……可以这样:一原序列下标为关键字建立Splay但是树的节点编号为此位置上的值是第几小。这样,每次就可以维护好Splay然后直接就可求出第i小的值的位置:它所在的节点的左子树大小+1,因为它将被置于前面不会被再次反转,为了方便可以将这个点删掉,没必要真删,只要将它所在子树大小-1,它的dat变成0。注意的是更新的顺序,自底向上更新子树大小时要先更新下面再更新上面,而传递反转的bool标记要先更新上面再更新下面。
[代码]:
View Code
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; const int INF=0x7fffffff; const int MAXN=110000; struct node { int dat,size,c[2],f; bool rev; }tree[MAXN]; int N,root=0,tn=0; int p[MAXN],a[MAXN],b[MAXN]; void Downdate(int v) { if (!v || !tree[v].rev) return ; tree[v].rev=0; tree[tree[v].c[0]].rev=!tree[tree[v].c[0]].rev; tree[tree[v].c[1]].rev=!tree[tree[v].c[1]].rev; //swap(tree[v].c[0],tree[v].c[1]); int t=tree[v].c[0]; tree[v].c[0]=tree[v].c[1],tree[v].c[1]=t; } void Update(int v) { if (!v) return ; //printf("%d %d)))\n",tree[6].c[0],tree[6].c[1]); tree[v].size=tree[tree[v].c[0]].size+tree[tree[v].c[1]].size+tree[v].dat; //printf("%d %d %d %d %d %d***\n",v,tree[v].size,tree[v].c[0],tree[v].c[1],tree[tree[v].c[0]].size,tree[tree[v].c[1]].size); } void rotate(int x,int o) { int y=tree[x].f; tree[y].c[o]=tree[x].c[!o]; tree[tree[y].c[o]].f=y; tree[x].f=tree[y].f; if (tree[tree[y].f].c[0]==y) tree[tree[y].f].c[0]=x; else tree[tree[y].f].c[1]=x; tree[y].f=x; tree[x].c[!o]=y; if (root==y) root=x; Update(y); Update(x); } void Splay(int x,int y) { while (tree[x].f!=y) { Downdate(tree[tree[x].f].f); Downdate(tree[x].f); Downdate(x); if (tree[tree[x].f].f==y) { if (tree[tree[x].f].c[0]==x) rotate(x,0); else rotate(x,1); } else if (tree[tree[tree[x].f].f].c[0]==tree[x].f) { if (tree[tree[x].f].c[0]==x) rotate(tree[x].f,0),rotate(x,0); else rotate(x,1),rotate(x,0); } else { if (tree[tree[x].f].c[1]==x) rotate(tree[x].f,1),rotate(x,1); else rotate(x,0),rotate(x,1); } } //Update(x); } void debug(int v) { //Downdate(v); //Update(v); if (tree[v].c[0]) debug(tree[v].c[0]); printf("%d %d %d %d %d %d\n",v,tree[v].c[0],tree[v].c[1],tree[v].size,tree[v].f,tree[v].dat); if (tree[v].c[1]) debug(tree[v].c[1]); //Update(v); } int Find(int v) { int pos; Splay(v,0); //Update(v); //printf("%d\n",root); //debug(root); //printf("\n/8/==================\n"); if (tree[v].c[0]) { pos=tree[tree[v].c[0]].size+1; tree[tree[v].c[0]].rev=!tree[tree[v].c[0]].rev; } else pos=1; tree[v].dat=0; tree[v].size--; return pos; } int main() { freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); scanf("%d",&N); for (int i=1;i<=N;i++) scanf("%d",&a[i]),p[a[i]]=i; sort(a+1,a+N+1); for (int i=1;i<=N;i++) b[p[a[i]]]=i; //for (int i=1;i<=N;i++) printf("%d ",b[i]); //printf("\n"); for (int i=1;i<=N;i++) { tree[b[i]].size=i; tree[b[i]].rev=0; tree[b[i]].dat=1; tree[b[i]].c[0]=i>1?b[i-1]:0; tree[b[i]].c[1]=0; tree[b[i]].f=i<N?b[i+1]:0; } root=b ; //debug(N); //for (int i=1;i<=N;i++) printf("%d %d %d %d\n",b[i],tree[b[i]].c[0],tree[b[i]].c[1],tree[b[i]].f); //printf("%d\n",root); for (int j=1;j<=N;j++) { //debug(root); //printf("\n//==================\n"); //for (int i=1;i<=N;i++) printf("%d %d %d %d %d\n",b[i],tree[b[i]].c[0],tree[b[i]].c[1],tree[b[i]].f,tree[b[i]].rev); printf("%d ",Find(j)+j-1); } printf("\n"); return 0; }
相关文章推荐
- [1103模拟赛][noi导刊第八期模拟题十六]
- [XJOI NOI2015模拟题13] C 白黑树 【线段树合并】
- 花海漫步 NOI模拟题
- Jzoj2921【NOI2012模拟题】字符串识别
- [XJOI NOI2015模拟题13] A 神奇的矩阵 【分块】
- NOI Newnode模拟题 第二题 DP 单调性优化 三分法
- 2018_2_10_Football Sort大模拟题_排序__格式
- 上下界 又见上下界 noi模拟题snake
- [XJOI NOI2015模拟题13] B 最小公倍数 【找规律】
- 无聊小玩意 用sort实现数组的逆序!!
- leetcode之Sort List
- Codevs 1800 假面舞会 2008年NOI全国竞赛
- [单纯形+对偶] BZOJ1061: [Noi2008]志愿者招募
- Problem 1462 - Books changing(模拟题STL数据结构)
- uva 227 模拟题
- [20, 3, 10].sort()
- java基础——collections.sort()排序方法使用方法
- 了解 sort 和 uniq 命令 (包括 uniq 的 -u 和 -d 选项)
- linux下sort用法
- sort对字符串排序