BZOJ 3506 机械排序臂 splay

    这是宝宝第二次敲splay了(如果LCT不算的话),还好吧!为什么自己写的TLE了呢?找个时间写下对拍吧!暂时还是要学习别人的代码的。一开始的思路是找到最小的点后,返回距离,然后删掉。在这里更深刻地体会到了自己的天真无邪,too young too simple , (假设当前的根是我们要删除的)以为只要把左子节点的父亲修改为右子结点, 右子结点的左儿子设成左子结点,然后把右子结点更新为根就好。(有没有发现问题所在?,右子结点原来的左儿子怎么办?)那好问题出现了就要寻求解决的方法了,我是这样想的,在右子树里一直往左走,走到第一个没有左子结点的位置,返回其标号,然后我们再把它旋转到根,然后……(你懂的)。然而这个TLE了。 其实这还不是我最开始的我,最开始的我是这样的,弄了左右边界,然后发现边界都被我翻转了,(有没有感到我的愚蠢)。后来再次Orz了黄学长的代码,当然我自己是做了修改的。加油了。splay还是很重要的。(我不想做源程狗。)

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<algorithm>
  4 #define lc c[k][0]
  5 #define rc c[k][1]
  6 #define rep(i,j,k) for(int  i = j;  i <= k; i++) 
  7 #define maxn 100233
  8 using namespace std;
  9 
 10 struct node{
 11 int v, pos;
 12 bool operator < (const node&rhs) const{
 13     return pos < rhs.pos;
 14 }
 15 } nod[maxn];
 16 
 17 bool cmp(node a,node b)
 18 {
 19     return a.v < b.v || (a.v == b.v && a.pos < b.pos ); 
 20 }
 21 
 22 int read()
 23 {
 24     int s = 0, t = 1; char c = getchar();
 25     while( !isdigit(c) ){
 26         if( c == '-' )  t= -1; c = getchar();
 27     }
 28     while( isdigit(c) ){
 29         s =s * 10 + c - '0'; c= getchar();
 30     }
 31     return s * t;
 32 }
 33 
 34 int s[maxn], pa[maxn], c[maxn][2], mn[maxn], v[maxn], root;
 35 bool rev[maxn];
 36 
 37 void pushdown(int k)
 38 {
 39     if( rev[k] ){
 40         rev[k] ^= 1, rev[lc] ^= 1, rev[rc] ^= 1;
 41         swap(lc,rc);
 42     } 
 43 }
 44 
 45 void maintain(int k)
 46 {
 47     mn[k] = k;
 48     if( v[mn[lc]] < v[mn[k]] ) mn[k] = mn[lc];
 49     if( v[mn[rc]] < v[mn[k]] ) mn[k] = mn[rc];
 50     s[k] = s[lc] + s[rc] + 1; 
 51 }
 52 
 53 void rorate(int k,int &root)
 54 {
 55     int fa = pa[k], gfa = pa[fa];
 56     int l = c[fa][1] == k, r = l ^ 1;
 57     if( fa != root ){
 58         c[gfa][c[gfa][1] == fa] = k;
 59     } else root = k;
 60     pa[fa] = k, pa[c[k][r]] = fa, pa[k] = gfa;
 61     c[fa][l] = c[k][r], c[k][r] = fa; maintain(fa), maintain(k);
 62 }
 63 
 64 int q[maxn];
 65 void splay(int k,int &root)
 66 {
 67     int top = 0; q[++top] = k;
 68     for(int x = k; x != root; x = pa[x] ) q[++top] = pa[x];
 69     while( top ) pushdown(q[top--]);
 70     while( k != root ){
 71         int fa = pa[k], gfa = pa[fa];
 72         if( fa != root ) {
 73             if( c[gfa][1] == fa ^ c[fa][1] == k ) rorate(k,root);
 74             else rorate(fa,root);
 75         }
 76         rorate(k,root);
 77     }
 78 }
 79 
 80 void build(int l,int r,int pre)
 81 {
 82     if( l > r ) return;
 83     int mid = (l+r)>>1;
 84     c[pre][pre < mid] = mid; pa[mid] = pre; v[mid] = nod[mid].v, mn[mid] = mid;
 85     c[mid][0] = c[mid][1] = 0;
 86     if( l < r ){
 87         build(l,mid-1,mid); build(mid+1,r,mid);
 88         maintain(mid);
 89     } else s[mid] = 1;
 90 }
 91 
 92 int rank(int x,int k)
 93 {
 94     if( rev[k] ) pushdown(k);
 95     if( s[lc] >= x ) return rank(x,lc);
 96     else if( s[lc] + 1 < x ) return rank(x-s[lc]-1,rc);
 97     else return k;
 98 }
 99 
100 int query_min(int x,int y)
101 {
102     x = rank(x,root), y = rank(y+2,root);
103     splay(x,root); splay(y,c[x][1]);
104     return mn[c[y][0]]; 
105 }
106 
107 void rever(int x,int y)
108 {
109     x = rank(x,root), y = rank(y+2,root);
110     splay(x,root); splay(y,c[x][1]);
111     rev[c[y][0]] ^= 1;
112 }
113 
114 void out(int k)
115 {
116     if( lc ) out(lc);
117     cout<<v[k]<<endl;
118     if( rc ) out(rc);
119 }
120 
121 int main()
122 {
123     int n;
124     while( scanf("%d", &n) && n ){
125     v[0] = nod[1].v = nod[n+2].v = 0x7fffffff;
126     rep(i,2,n+1) nod[i].v = read(), nod[i].pos = i;
127     sort(nod+2,nod+2+n,cmp); root = (3+n)>>1;
128     rep(i,2,n+1) nod[i].v = i-1;
129     sort(nod+2,nod+2+n);  build(1,n+2,0);  //out(root);
130     rep(i,1,n){
131         int q = query_min(i,n); splay(q,root);
132         printf("%d ", s[c[q][0]] );
133         rever(i,s[c[q][0]]);
134     }
135             puts("");
136     }
137     return 0;
138 }

 

posted on 2016-01-12 13:47  83131  阅读(317)  评论(1编辑  收藏  举报

导航