【题目】
Description
您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是 5 4 3 2 1,翻转区间是 [ 2 , 4 ] 的话,结果是 5 2 3 4 1
Input
第一行为 ,
表示初始序列有 个数,这个序列依次是 ( 1 , 2 …… , , ), 表示翻转操作次数
接下来 行每行两个数 [ , ] 数据保证 1 ≤ ≤ ≤
Output
输出一行 个数字,表示原始序列经过 次变换后的结果
Sample Input
5 3 1 3 1 3 1 4
Sample Output
4 3 2 1 5
HINT
N,M ≤ 100000
【分析】
裸题,由于我是初学,一个简单的错误卡了我好久。。。
大体思路就是以中间的为根,左右两边递归建树(以数组下标来建),然后对于每组询问 ,都把 转到根, 转到根的右子树,这样 的左子树就是 [ , ] 间的所有数,对它左子树的根打一个翻转标记(和线段树的差不多),每次若发现要翻转,就下传标记,并翻转左右两子树,最后中序遍历就是答案
还有一个玄学问题:我们要建立虚点 和 ,不加会过不了,我也不知道为什么
【代码】
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 500005
#define lc(x) son[x][0]
#define rc(x) son[x][1]
using namespace std;
int n,m,t=0,root=0;
int fa[N],num[N],val[N],lazy[N],size[N],son[N][2];
int Get(int x)
{
return x==rc(fa[x]);
}
void pushup(int x)
{
size[x]=size[lc(x)]+size[rc(x)]+num[x];
}
void pushdown(int root)
{
if(!lazy[root]) return;
swap(lc(root),rc(root));
lazy[lc(root)]^=1;
lazy[rc(root)]^=1;
lazy[root]=0;
}
void rotate(int &root,int x)
{
int y=fa[x],z=fa[y];
int r1=Get(x),r2=Get(y);
pushdown(y),pushdown(x);
if(y==root) root=x;
else son[z][r2]=x;
son[y][r1]=son[x][r1^1],fa[son[x][r1^1]]=y;
son[x][r1^1]=y,fa[y]=x,fa[x]=z;
pushup(y),pushup(x);
}
void splay(int &root,int x)
{
int y=fa[x],z=fa[y];
while(x!=root)
{
if(y!=root)
{
if(Get(x)==Get(y)) rotate(root,y);
else rotate(root,x);
}
rotate(root,x);
y=fa[x],z=fa[y];
}
}
int newnode(int x)
{
lazy[++t]=0;
size[t]=num[t]=1;
val[t]=x,lc(t)=rc(t)=0;
return t;
}
int build(int l,int r,int father)
{
if(l>r) return 0;
int mid=(l+r)>>1;
int x=newnode(mid);
fa[x]=father;
lc(x)=build(l,mid-1,x);
rc(x)=build(mid+1,r,x);
pushup(x);
return x;
}
int findkth(int root,int k)
{
if(k>size[root]) return k=size[root];
while(root)
{
pushdown(root);
if(k==size[lc(root)]+1) return root;
if(k<=size[lc(root)]) root=lc(root);
else
{
k-=size[lc(root)]+num[root];
root=rc(root);
}
}
return root;
}
void flip(int l,int r)
{
int x=findkth(root,l);
int y=findkth(root,r+2);
splay(root,x),splay(rc(x),y);
lazy[lc(y)]^=1;
}
void dfs(int root)
{
if(!root) return;
pushdown(root);
dfs(lc(root));
if(val[root]>=1&&val[root]<=n)
printf("%d ",val[root]);
dfs(rc(root));
}
int main()
{
int l,r,i;
scanf("%d%d",&n,&m);
root=build(0,n+1,0);
for(i=1;i<=m;++i)
{
scanf("%d%d",&l,&r);
flip(l,r);
}
dfs(root);
return 0;
}