Tyvj:1729 文艺平衡树(saply练习)
您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1
第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2……n-1,n) m表示翻转操作次数
接下来m行每行两个数[l,r] 数据保证 1<=l<=r<=n
Output
输出一行n个数字,表示原始序列经过m次变换后的结果
Sample Input
5 3
1 3
1 3
1 4
Sample Output
4 3 2 1 5
没什么可以说的,蓝桥杯求稳,多写点。
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int maxn=100010; int N; void swap(int &x,int &y){ int tmp=x; x=y;y=tmp; } struct Splay { int ch[maxn][2],fa[maxn],key[maxn],sz[maxn],lazy[maxn],rt,cnt; Splay(){ rt=cnt=0; } int get(int x) { return ch[fa[x]][1]==x; } void pushdown(int Now){ if(lazy[Now]){ swap(ch[Now][0],ch[Now][1]); if(ch[Now][0]) lazy[ch[Now][0]]^=1; if(ch[Now][1]) lazy[ch[Now][1]]^=1; lazy[Now]=0; } } void pushup(int Now){ sz[Now]=1+sz[ch[Now][0]]+sz[ch[Now][1]]; } int build(int L,int R,int f) { if(L>R) return 0; int Mid=(L+R)>>1; if(!rt) rt=Mid; key[Mid]=Mid; fa[Mid]=f; lazy[Mid]=0; ch[Mid][0]=build(L,Mid-1,Mid); ch[Mid][1]=build(Mid+1,R,Mid); pushup(Mid); return Mid; } int find(int x) { int Now=rt; while(true){ pushdown(Now); if(sz[ch[Now][0]]>=x) Now=ch[Now][0]; else { x=x-sz[ch[Now][0]]-1; if(x==0) return Now; Now=ch[Now][1]; } } } void rotate(int x) { int old=fa[x],fold=fa[old],opt=get(x); pushdown(old); pushdown(x); ch[old][opt]=ch[x][opt^1]; fa[ch[x][opt^1]]=old; ch[x][opt^1]=old; fa[old]=x; fa[x]=fold; pushup(old); pushup(x); if(fold) ch[fold][ch[fold][1]==old]=x; } void splay(int x,int y) { for(int f;(f=fa[x])!=y;rotate(x)) if(fa[f]!=y) rotate(get(f)==get(x)?f:x); if(!y) rt=x; } void revers(int x,int y) { x=find(x); splay(x,0); y=find(y); splay(y,x); lazy[ch[ch[rt][1]][0]]^=1; } void print(int Now) { pushdown(Now); if(ch[Now][0]) print(ch[Now][0]); if(key[Now]>1&&key[Now]<N+2) printf("%d ",key[Now]-1); if(ch[Now][1]) print(ch[Now][1]); } }S; int main() { int T,a,b; scanf("%d%d",&N,&T); S.build(1,N+2,0); while(T--){ scanf("%d%d",&a,&b); S.revers(a,b+2); } S.print(S.rt); return 0; }
N,M<=100000
It is your time to fight!