题目描述
您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1
输入输出格式
输入格式:
第一行为n,m n表示初始序列有n个数,这个序列依次是 (1,2, \cdots n-1,n)(1,2,⋯n−1,n) m表示翻转操作次数
接下来m行每行两个数 [l,r][l,r] 数据保证 1 \leq l \leq r \leq n 1≤l≤r≤n
输出格式:
输出一行n个数字,表示原始序列经过m次变换后的结果
输入输出样例
输入样例#1:
5 3
1 3
1 3
1 4
输出样例#1:
4 3 2 1 5
说明
n,m≤100000
分析:splay模版题,关键字为位置,记录下数字(其实就是1–n),和之前学的lct差不多。
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
const int maxn=1e5+7;
using namespace std;
struct node{
int l,r,s,fa,size;
bool rev;
}t[maxn];
int n,m,root,x,y;
int find(int x,int k)//查询区间第k小
{
if (t[x].rev)//先清标记
{
t[x].rev^=1;
swap(t[x].l,t[x].r);
if (t[x].l) t[t[x].l].rev^=1;
if (t[x].r) t[t[x].r].rev^=1;
}
int size=t[t[x].l].size;
if (size==k-1) return x;
if (k<=size) return find(t[x].l,k);
else return find(t[x].r,k-size-1);
}
void remove(int x)//清空标记
{
if (x!=root) remove(t[x].fa);
if (t[x].rev)
{
t[x].rev^=1;
swap(t[x].l,t[x].r);
if (t[x].l) t[t[x].l].rev^=1;
if (t[x].r) t[t[x].r].rev^=1;
}
}
void updata(int x)
{
t[x].size=t[t[x].l].size+t[t[x].r].size+1;
}
void rttr(int x)
{
int y=t[x].l;
t[x].l=t[y].r;
if (t[y].r) t[t[y].r].fa=x;
if (t[t[x].fa].l==x) t[t[x].fa].l=y;
else if (t[t[x].fa].r==x) t[t[x].fa].r=y;
t[y].fa=t[x].fa;
t[x].fa=y;
t[y].r=x;
updata(x); updata(y);
}
void rttl(int x)
{
int y=t[x].r;
t[x].r=t[y].l;
if (t[y].l) t[t[y].l].fa=x;
if (t[t[x].fa].l==x) t[t[x].fa].l=y;
else if (t[t[x].fa].r==x) t[t[x].fa].r=y;
t[y].fa=t[x].fa;
t[x].fa=y;
t[y].l=x;
updata(x); updata(y);
}
bool isroot(int x)
{
return t[x].fa==0;
}
void splay(int x)
{
remove(x);
while (!isroot(x))
{
int p=t[x].fa,g=t[p].fa;
if (p==root)
{
if (x==t[p].l) rttr(p);
else rttl(p);
}
else
{
if (x==t[p].l)
{
if (p==t[g].l) rttr(p),rttr(g);
else rttr(p),rttl(g);
}
else
{
if (p==t[g].l) rttl(p),rttr(g);
else rttl(p),rttl(g);
}
}
}
root=x;
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
{
t[i].s=i;
t[i].size=n-i+1;
if (i>1) t[i].fa=i-1;
if (i<n) t[i].r=i+1;
}
root=1;
for (int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
if ((x==1) && (y==n)) t[root].rev^=1;
else
{
if (x==1)
{
int v=find(root,y+1);
splay(v);
t[t[v].l].rev^=1;
}
else
{
if (y==n)
{
int v=find(root,x-1);
splay(v);
t[t[v].r].rev^=1;
}
else
{
int u=find(root,x-1),v=find(root,y+1);
splay(v); splay(u);
t[t[v].l].rev^=1;
}
}
}
}
for (int i=1;i<=n;i++)
{
int u=find(root,i);
printf("%d ",t[u].s);
}
}