传送门
功能:实现区间反转
比如当前需要反转 [ l , r ] ,那么只需要把 l - 1 和 r + 1 分别旋到根节点,让后根节点右子树的左子树就是 [ l , r ] 区间内的数,在上面加一个 tag 懒标即可。
注意各个地方pushdown。
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define pb push_back
#define mk make_pair
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int N=1000010,mod=1e9+7,INF=0x3f3f3f3f;
const double eps=1e-6;
struct Splay
{
struct node
{
int v,father;//v是结点值,father是父亲结点
int ch[2];//ch[0] 左节点 ch[1] 右结点
int sum;//包含自己下面有多少元素(非结点)
int recy;//该结点元素出现次数(非结点)
int tag;//区间标记
};
node e[N];
int idx;
int rot,a[N];
void update(int x)//更新当前结点sum
{
e[x].sum=e[e[x].ch[0]].sum+e[e[x].ch[1]].sum+e[x].recy;
}
int identify(int x)//确定当前结点是父亲的左孩子还是右孩子
{
return e[e[x].father].ch[0]==x? 0:1;
}
void connect(int x,int f,int son)//x作为f的son(左右)儿子
{
e[x].father=f;
e[f].ch[son]=x;
}
void pushdown(int x)//标记
{
if(x&&e[x].tag)
{
e[e[x].ch[0]].tag^=1;
e[e[x].ch[1]].tag^=1;
swap(e[x].ch[0],e[x].ch[1]);
e[x].tag=0;
}
}
void rotate_tree(int x)//旋转节点
{
int y=e[x].father;
int mroot=e[y].father;
pushdown(x); pushdown(y);
int mrootson=identify(y);
int yson=identify(x);
int B=e[x].ch[yson^1];
connect(B,y,yson); connect(y,x,(yson^1)); connect(x,mroot,mrootson);
update(y); update(x);
}
void splay_tree(int x,int goal)//伸展操作
{
for(int t;(t=e[x].father)!=goal;rotate_tree(x))
if(e[t].father!=goal) rotate_tree(identify(x)==identify(t)? t:x);
if(goal==0) rot=x;
}
int build_tree(int l,int r,int fa)//递归建树
{
if(l>r) return 0;
int mid=l+r>>1;
int now=++idx;
e[now].father=fa;
e[now].ch[0]=e[now].ch[1]=0;
e[now].recy++,e[now].sum++;
e[now].v=a[mid];
e[now].ch[0]=build_tree(l,mid-1,now);
e[now].ch[1]=build_tree(mid+1,r,now);
update(now);
return now;
}
int find_tree(int v)
{
int now=rot;
while(1)
{
pushdown(now);
if(v<=e[e[now].ch[0]].sum)
now=e[now].ch[0];
else
{
v-=e[e[now].ch[0]].sum+e[now].recy;
if(v<=0) return now;
now=e[now].ch[1];
}
}
return 0;
}
void reverse(int x,int y)
{
int l=x-1,r=y+1;
l=find_tree(l),r=find_tree(r);
splay_tree(l,0);
splay_tree(r,l);
int pos=e[rot].ch[1];
pos=e[pos].ch[0];
e[pos].tag^=1;
}
void dfs(int now)//输出
{
pushdown(now);
if(e[now].ch[0]) dfs(e[now].ch[0]);
if(e[now].v!=INF&&e[now].v!=-INF) printf("%d ",e[now].v);
if(e[now].ch[1]) dfs(e[now].ch[1]);
}
void solve()
{
int n,m;
scanf("%d%d",&n,&m);
a[1]=-INF,a[n+2]=INF;
for(int i=1;i<=n;i++) a[i+1]=i;
rot=build_tree(1,n+2,0);
while(m--)
{
int x,y; scanf("%d%d",&x,&y);
reverse(x+1,y+1);
}
dfs(rot);
}
}S;
int main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);
S.solve();
return 0;
}
/*
*/