Codevs1743--反转卡片
在Splay上打反转标记
自己脑补了一下,感觉就是在旋转的时候传递一下标记免得被破坏就可以了。
具体交换左右儿子然后标记下传。
代码:
#include<bits/stdc++.h> #define MAXN 300005 #define MAXM 3005 #define INF 1000000000 #define MOD 1000000 #define LL long long using namespace std; int n; namespace Splay{ const int L=0,R=1; int root; struct Node{ int son[2],v,sz,par; bool turn; }x[MAXN]; inline void Push_down(int num) { swap(x[num].son[L],x[num].son[R]);x[num].turn^=1; x[x[num].son[L]].turn^=1;x[x[num].son[R]].turn^=1; } inline void rotate(int num,int p) { int pa=x[num].par,t=x[num].sz; if(x[pa].par) x[x[pa].par].son[x[x[pa].par].son[L]==pa?L:R]=num; x[num].sz=x[pa].sz;x[pa].sz-=t-x[x[num].son[p]].sz; x[pa].son[p^1]=x[num].son[p];if(x[num].son[p]) {x[x[num].son[p]].par=pa;} x[num].son[p]=pa;x[num].par=x[pa].par;x[pa].par=num; } inline void Splay_N(int num,int gl) { int par,ppar; while(x[num].par!=gl) { if(x[x[x[num].par].par].turn) Push_down(x[x[num].par].par); if(x[x[num].par].turn) Push_down(x[num].par);if(x[num].turn) Push_down(num); if(x[x[num].par].par==gl) {rotate(num,x[x[num].par].son[L]==num?R:L);break;} par=x[x[num].par].son[L]==num?R:L;ppar=x[x[x[num].par].par].son[L]==x[num].par?R:L; if(par==ppar) rotate(x[num].par,ppar),rotate(num,par); else rotate(num,par),rotate(num,ppar); } if(!gl) root=num; } int Build_Splay(int l,int r,int fr) { if(r<l) return 0; int mid=l+r>>1;x[mid].par=fr; if(l==r) {x[mid].sz=1;return mid;} x[mid].son[L]=Build_Splay(l,mid-1,mid); x[mid].son[R]=Build_Splay(mid+1,r,mid); x[mid].sz=x[x[mid].son[L]].sz+x[x[mid].son[R]].sz+1; return mid; } void Build() {root=Build_Splay(1,n+1,0);} int Qurey(int k) { int now=root; while(true) { if(x[now].turn) k=x[now].sz-k+1; if(x[x[now].son[L]].sz==k-1) {Splay_N(now,0);return now;} if(x[x[now].son[L]].sz<k) {k-=x[x[now].son[L]].sz+1;now=x[now].son[R];} else now=x[now].son[L]; } } void Turn(int k) { Splay_N(Qurey(k),0); x[x[root].son[L]].turn^=1; } bool Check() { int t=Qurey(1);t=x[t].v; if(t==1) return 0; Turn(1+t); /*for(int i=1;i<=n;i++) cout<<x[Qurey(i)].v<<" "; cout<<endl;*/ return 1; } } using namespace Splay; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&x[i].v); } Build(); for(int i=1;i<=100000;i++) { if(!Check()) {printf("%d\n",i-1);break;} } return 0; }
- [CODEVS1743]反转卡片(splay)
- code vs 1743 反转卡片(splay)
- 【codevs1743】 反转卡片
- CodeVS1743 反转卡片
- codevs 1743 反转卡片
- codevs 1743 反转卡片
- codevs 1743 反转卡片/splay tree
- Codevs 1743 反转卡片 [Splay]
- codevs 1743 反转卡片
- 【codevs1743】反转卡片
- Codevs_P1743 反转卡片(块状链表+SplayTree)
- codevs1743
- 【基础练习】【模拟】codevs1704 卡片游戏题解
- code vs 3243 区间反转(线段树)
- Codevs 1743 反转卡片(splay)
- [CODEVS1130]数字反转
- cv1743 反转卡片(splay)
- codevs 数字反转 1130
- 1743 反转卡片
- 【codevs 1743】反转卡片 splay的应用