code[VS]1743反转卡片 SPlay

来源:互联网 发布:每周开户数据 编辑:程序博客网 时间:2024/06/10 10:04

弟弟救我。

原本想今晚不来机房的,结果硬生生写了个平衡树再回去。


SPlay区间翻转,为了防止越界可以在最后面增加一个虚拟节点。

#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#define INF 1<<30#define N 600050using namespace std;int siz[N],tr[N],s[N][2],tag[N],fa[N];int a[N],rt,cnt,n;inline void update(int t) { siz[t] = siz[ s[t][0] ] + siz[ s[t][1] ] + 1; }void rotate(int x,int &k) {int y = fa[x] , z = fa[y] , l = s[y][0] != x , r = l ^ 1;if (y == k) k = x; else {if (s[z][0] == y) s[z][0] = x; else s[z][1] = x; }fa[x] = z; fa[y] = x; fa[ s[x][r] ] = y;s[y][l] = s[x][r]; s[x][r] = y;update(y); update(x);}void SPlay(int x) {while (x != rt) {int y = fa[x] , z = fa[y];if (y != rt) {if ((s[z][0] == y)^(s[y][0] == x)) rotate(x,rt);elserotate(y,rt);} rotate(x,rt);}}inline void push_down(int t) {if (!tag[t]) return ;swap(s[t][0],s[t][1]);tag[ s[t][0] ] ^= 1;tag[ s[t][1] ] ^= 1;tag[t] ^= 1;}int kth(int k,int x) {push_down(x);int tmp = siz[ s[x][0] ] + 1;if (tmp == k) return x;return tmp > k ? kth(k,s[x][0]) : kth(k-tmp,s[x][1]);}void build(int l,int r,int &t,int f) {//if (l > r) return ;int mid = (l + r) >> 1;tr[ t=++cnt ] = mid;fa[t] = f;siz[t] = 1;if (l == r) return ;if (l <= mid-1) build(l,mid-1,s[t][0],t);if (mid+1 <= r) build(mid+1,r,s[t][1],t);update(t);}inline void solve() {build(1,n,rt,0);int tmp = 0 , ans = 0 , deb = 0;while (( tmp = a[ tr[ deb = kth(1,rt) ] ] ) != 1) {SPlay(deb);int p = kth(tmp+1,rt);SPlay(p);tag[ s[rt][0] ] ^= 1;ans++;}printf("%d\n",ans);}inline void init() {scanf("%d",&n);for (int i=1;i<=n;i++) scanf("%d",&a[i]);a[++n] = INF;}int main(){init();solve();return 0;}


0 0
原创粉丝点击