您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是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
输出一行n个数字,表示原始序列经过m次变换后的结果
5 3
1 3
1 3
1 4
4 3 2 1 5
N,M<=100000
平衡树
splay区间操作,蛋疼了我半天…………
每个节点存儿子、父亲、出现次数、子树大小、权值。其中权值为该节点代表的序列的位置的那个值。
权值并不用来维护平衡树的性质,维护平衡树的性质的那个权值(也就是下标)并不存下来。旋转并不会破坏这个性质。
这样就可以像寻找第K大那样找到序列中某一个点了。
翻转区间:交换左右儿子的指针。
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int SZ = 1000010;
const int INF = 1000000010;
struct node{
node *ch[2],*f;
int sz,cnt,v,x;
bool flag;
void maintain() { sz = ch[0] -> sz + ch[1] -> sz + cnt; }
void setc(node *x,int d) { (ch[d] = x) -> f = this; }
int cmp(int x)
{
if(x == v) return -1;
return x < v ? 0 : 1;
}
int dir() { return f -> ch[1] == this; }
void pushdown();
}T[SZ], *root, *null;
int Tcnt = 0;
void node::pushdown()
{
if(flag)
{
flag = 0;
if(ch[1] != null) ch[1] -> flag ^= 1;
if(ch[0] != null) ch[0] -> flag ^= 1;
swap(ch[0],ch[1]);
}
}
node* newnode(int v,node *f)
{
node *k = T + (Tcnt ++);
k -> ch[1] = k -> ch[0] = null;
k -> v = v;
k -> sz = k -> cnt = 1;
k -> flag = 0;
k -> f = f;
return k;
}
void rotate(node *p)
{
p -> f -> pushdown(); p -> pushdown();
node *fa = p -> f;
int d = p -> dir();
fa -> f -> setc(p,fa -> dir());
fa -> setc(p -> ch[d ^ 1],d); fa -> maintain();
p -> setc(fa,d ^ 1); p -> maintain();
if(fa == root) root = p;
}
void splay(node *p,node *rt = null)
{
while(p -> f != rt)
{
p -> pushdown();
if(p -> f -> f == rt) rotate(p);
else
{
if(p -> dir() == p -> f -> dir()) rotate(p -> f),rotate(p);
else rotate(p),rotate(p);
}
}
}
node* find(node *p,int k)
{
while(p != null)
{
p -> pushdown();
int l = p -> ch[0] -> sz + 1;
int r = p -> ch[0] -> sz + p -> cnt;
if(l <= k && k <= r) return p;
if(k > r) k -= r,p = p -> ch[1];
else p = p -> ch[0];
}
}
void reverse(node *p,int l,int r)
{
l ++; r ++;
node* pre = find(root,l - 1);
node* suf = find(root,r + 1);
splay(pre); splay(suf,root);
root -> ch[1] -> ch[0] -> flag ^= 1;
}
void build(node* &p,int l,int r,node *fa)
{
if(l > r) return ;
int mid = (l + r) >> 1;
p = newnode(mid,fa);
build(p -> ch[0],l,mid - 1,p);
build(p -> ch[1],mid + 1,r,p);
p -> maintain();
}
int n,m;
void init()
{
null = newnode(-INF,null);
null -> sz = null -> cnt = 0;
root = newnode(-INF,null);
root -> ch[1] = newnode(INF,root);
build(root -> ch[1] -> ch[0],1,n,root -> ch[1]);
root -> ch[1] -> maintain();
root -> maintain();
}
int main()
{
scanf("%d%d",&n,&m);
init();
while(m --)
{
int l,r;
scanf("%d%d",&l,&r);
reverse(root,l,r);
}
for(int i = 1;i <= n;i ++)
printf("%d ",(find(root,i + 1)) -> v); return 0; }