codevs1743

http://codevs.cn/problem/1743/

splay区间翻转。

数字在原序列中的位置保存在splay的data[]中。splay中点的编号为原序列的数字大小。

每次pushdown只在find时进行就行,因为find结束时splay只会改动i点祖先的信息,而其余时候没有splay操作了。

记得加个+INF 一个-INF。

  1 #include<cstdio>
  2 #include<algorithm>
  3 using namespace std;
  4 #define N 400000
  5 #define INF 2000000000
  6 int lazy[N],s[N][3],f[N],cnt[N],data[N],root,total;//son:1left 2right 
  7 int fi,num,p,q,le[N],m,n,i,j,ans;
  8 char opt;
  9 struct lbz
 10 {
 11     int a,b;
 12 }x[N];
 13 bool cmp(lbz a,lbz b)
 14 {
 15     return a.a<b.a;
 16 }
 17 void rotate(int x,int w)//w:1leftZag 2rightZig
 18 {
 19     int y;
 20     y=f[x];
 21     cnt[y]=cnt[y]-cnt[x]+cnt[s[x][w]];
 22     cnt[x]=cnt[x]-cnt[s[x][w]]+cnt[y];
 23     s[y][3-w]=s[x][w];
 24     if (s[x][w]!=0)
 25         f[s[x][w]]=y;
 26     f[x]=f[y];
 27     if (f[y]!=0)
 28         if (y==s[f[y]][1])
 29             s[f[y]][1]=x;
 30         else
 31             s[f[y]][2]=x;
 32     f[y]=x;
 33     s[x][w]=y;
 34 }
 35 void splay(int x,int t)
 36 {
 37     int y;
 38     while (f[x]!=t)
 39     {
 40         y=f[x];
 41         if (f[y]==t)
 42             if (x==s[y][1]) 
 43                 rotate(x,2);
 44             else
 45                 rotate(x,1);
 46         else
 47             if (y==s[f[y]][1])
 48                 if (x==s[y][1])
 49                 {
 50                     rotate(y,2);
 51                     rotate(x,2);
 52                 }
 53                 else
 54                 {
 55                     rotate(x,1);
 56                     rotate(x,2);
 57                 }
 58             else
 59                 if (x==s[y][2])
 60                 {
 61                     rotate(y,1);
 62                     rotate(x,1);
 63                 }
 64                 else
 65                 {
 66                     rotate(x,2);
 67                     rotate(x,1);
 68                 }
 69     }
 70     if (f[x]==0) root=x;
 71 }
 72 
 73 int sea(int x,int w)
 74 {
 75     int t;
 76     t=x;
 77     while (1)
 78     {
 79         if (data[t]==w) break;
 80         if (w<=data[t])
 81         {
 82             if (s[t][1]==0) break;
 83             t=s[t][1];
 84         }
 85         else
 86         {
 87             if (s[t][2]==0) break;
 88             t=s[t][2];
 89         }
 90         
 91     }
 92     splay(t,0);
 93     return t;
 94 }
 95 void add(int w)
 96 {
 97     int x;
 98     if (total==0)
 99     {
100         total++;
101         f[1]=0;cnt[1]=1;data[1]=w;root=1;
102         return;
103     }
104     x=root;
105     while(1)
106     {
107         cnt[x]++;
108         if (w<=data[x])
109         {
110             if (s[x][1]==0)    break;
111             x=s[x][1];
112         }
113         else
114         {
115             if (s[x][2]==0)    break;
116             x=s[x][2]; 
117         }
118     }
119     total++;
120     data[total]=w;
121     f[total]=x;
122     cnt[total]=1;
123     if (w<=data[x])
124         s[x][1]=total;
125     else
126         s[x][2]=total;
127     splay(total,0);    
128 }
129 
130 void pushdown(int x)
131 {
132     lazy[x]^=1;
133     lazy[s[x][1]]^=1;
134     lazy[s[x][2]]^=1;
135     swap(s[x][1],s[x][2]);
136 }
137 int find(int k,int w)//w=1 Kthsmall;w=2 Kthbig
138 {
139     int i,t;
140     i=root;t=k;
141     if (lazy[i]==1)
142         pushdown(i);
143     
144     while (t!=cnt[s[i][w]]+1)
145     {
146 
147         if (t>cnt[s[i][w]]+1)
148         {
149             t-=cnt[s[i][w]]+1;
150             i=s[i][3-w];
151         }
152         else
153             i=s[i][w];    
154         if (lazy[i]==1)
155             pushdown(i);
156     }
157     splay(i,0);
158     return i;
159 }
160 
161 int rec(int l,int r)
162 {
163     int ll,rr;
164     ll=find(l,1);
165     rr=find(r+2,1);
166     splay(ll,0);
167     splay(rr,ll);
168     lazy[s[rr][1]]^=1;
169 }
170 int main()
171 {
172     scanf("%d",&n);
173     for (i=1;i<=n;i++)
174     {
175         scanf("%d",&x[i].a);
176         x[i].b=i;
177     }
178     sort(x+1,x+1+n,cmp);
179     for (i=1;i<=n;i++)
180         add(x[i].b);
181     add(1000000000);
182     add(-1000000000);
183     while (1)
184     {
185         fi=find(2,1);
186         if (fi==1) break;
187         rec(1,fi);
188         ans++;
189     }
190     printf("%d\n",ans);
191     return 0;        
192 }
View Code

 

posted @ 2016-09-13 21:15  lbz007  阅读(237)  评论(0编辑  收藏  举报
Live2D