3223. 文藝平衡樹【平衡樹-splay】
阿新 • • 發佈:2018-03-31
bsp ever tar ++i %d 變換 mar oid n+1
1 3
1 3
1 4
4 3 2 1 5
Description
您需要寫一種數據結構(可參考題目標題),來維護一個有序數列,其中需要提供以下操作:翻轉一個區間,例如原有序序列是5 4 3 2 1,翻轉區間是[2,4]的話,結果是5 2 3 4 1
Input
第一行為n,m n表示初始序列有n個數,這個序列依次是(1,2……n-1,n) m表示翻轉操作次數
接下來m行每行兩個數[l,r] 數據保證 1<=l<=r<=n
Output
輸出一行n個數字,表示原始序列經過m次變換後的結果
Sample Input
5 31 3
1 3
1 4
Sample Output
HINT
N,M<=100000
板子啊,常規操作
#include<iostream> #include<cstdio> #include<cstring> #define MAXN (100000+10) using namespace std; int Father[MAXN]; int Son[MAXN][2]; int Size[MAXN]; int Smark[MAXN]; int a[MAXN]; int Key[MAXN]; int Root; int n,m,l,r; int Get(int x) { return Son[Father[x]][1]==x; } void Update(int x) { Size[x]=Size[Son[x][1]]+Size[Son[x][0]]+1; } void Pushdown(int x) { if (x && Smark[x]) { Smark[Son[x][0]]^=1; Smark[Son[x][1]]^=1; swap(Son[x][0],Son[x][1]); Smark[x]=0; } } void Rotate(int x) { Pushdown(Father[x]); Pushdown(x); int fa=Father[x]; int fafa=Father[fa]; int wh=Get(x); Son[fa][wh]=Son[x][wh^1]; Father[fa]=x; if (Son[fa][wh]) Father[Son[fa][wh]]=fa; Father[x]=fafa; Son[x][wh^1]=fa; if (fafa) Son[fafa][Son[fafa][1]==fa]=x; Update(fa); Update(x); } void Splay(int x,int tar) { for (int fa;(fa=Father[x])!=tar;Rotate(x)) if (Father[fa]!=tar) Rotate(Get(fa)==Get(x)?fa:x); if (!tar) Root=x; } void Build (int l,int r,int fa) { if (l>r) return; int mid=(l+r)/2; if (mid<fa) Son[fa][0]=mid; if (mid>fa) Son[fa][1]=mid; Father[mid]=fa; Size[mid]=1; Key[mid]=a[mid]; if (l==r) return; Build(l,mid-1,mid); Build(mid+1,r,mid); Update(mid); } int Findx(int x) { int now=Root; while (1) { Pushdown(now); if (x<=Size[Son[now][0]]) now=Son[now][0]; else { x-=Size[Son[now][0]]; if (x==1) return now; x-=1; now=Son[now][1]; } } } void Rever(int l,int r) { int f1=Findx(l); int f2=Findx(r+2); Splay(f1,0); Splay(f2,f1); Smark[Son[Son[Root][1]][0]]^=1; } void Write(int x) { Pushdown(x); if (Son[x][0]) Write(Son[x][0]); if (x>=2 && x<=n+1) printf("%d ",Key[x]); if (Son[x][1]) Write(Son[x][1]); } int main() { scanf("%d%d",&n,&m); for (int i=2;i<=n+1;++i) a[i]=i-1; Build(1,n+2,0);Root=(n+3)/2; for (int i=1;i<=m;++i) { scanf("%d%d",&l,&r); if (l>=r) continue; Rever(l,r); } Write(Root); }
3223. 文藝平衡樹【平衡樹-splay】