Description
题目描述
您需要写一种数据结构(可参考题目标题),来维护一个有序数列。
其中需要提供以下操作:翻转一个区间,例如原有序序列是 5\ 4\ 3\ 2\ 15 4 3 2 1,翻转区间是 [2,4][2,4] 的话,结果是 5\ 2\ 3\ 4\ 15 2 3 4 1。
输入格式
第一行两个正整数 n,mn,m,表示序列长度与操作个数。序列中第 ii 项初始为 ii。
接下来 mm 行,每行两个正整数 l,rl,r,表示翻转的区间。
输出格式
输出一行 nn 个正整数,表示原始序列经过 mm 次变换后的结果。
Code
#include <cstdio> #include <cstdlib> #include <algorithm> using namespace std; const int N=100010,inf=999999999; int sum,n,root,m,l,r,d[N],fa[N],size[N],s[N][2],v[N],tag[N]; inline int which(int x) { return x==s[fa[x]][0]?0:1; } inline void push_up(int g) { if(g){ size[g]=1; if(s[g][0]) size[g]+=size[s[g][0]]; if(s[g][1]) size[g]+=size[s[g][1]]; } } void built(int l,int r,int &g) { if(l>r) return ; g=++sum; size[g]=1; int mid=(l+r)>>1; v[g]=d[mid]; built(l,mid-1,s[g][0]); built(mid+1,r,s[g][1]); fa[s[g][0]]=fa[s[g][1]]=g; push_up(g); } inline void push_down(int g) { if(g && tag[g]){ tag[s[g][0]]^=1,tag[s[g][1]]^=1; swap(s[g][0],s[g][1]),tag[g]=0; } } inline int find(int x) { int now=root; while(1) { push_down(now); if(size[s[now][0]]>=x) now=s[now][0]; else { x-=size[s[now][0]]+1; if(x>0) now=s[now][1]; else return now; } } } inline void rotate(int x) { int f=fa[x],oldf=fa[f]; push_down(f),push_down(x); int w=which(x),ww=which(f); s[f][w]=s[x][w^1]; fa[s[x][w^1]]=f; fa[f]=x,fa[x]=oldf; s[x][w^1]=f; if(oldf) s[oldf][s[oldf][1]==f]=x; push_up(f),push_up(x); } inline void splay(int x,int g) { for(int i;(i=fa[x])!=g;rotate(x)) if(fa[i]!=g) rotate(which(i)==which(x)?i:x); if(g==0) root=x; } inline void re(int l,int r) { l=find(l-1),r=find(r+1); splay(l,0),splay(r,l); int pos=s[s[root][1]][0]; tag[pos]^=1; } void dfs(int x) { push_down(x); if(s[x][0]) dfs(s[x][0]); if(v[x]!=-inf && v[x]!=inf) printf("%d ",v[x]); if(s[x][1]) dfs(s[x][1]); } int main() { scanf("%d%d",&n,&m); d[1]=-inf,d[n+2]=inf; for(int i=1;i<=n;i++) d[i+1]=i; built(1,n+2,root); for(int i=0;i<m;i++) { scanf("%d%d",&l,&r); re(l+1,r+1); } dfs(root); return 0; }
原文地址:https://www.cnblogs.com/hsez-cyx/p/12244750.html
时间: 2024-10-18 09:39:57