3223: Tyvj 1729 文艺平衡树
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 5126 Solved: 3003
[ Submit][ Status][ Discuss]
Description
您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1
Input
第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2……n-1,n) m表示翻转操作次数
接下来m行每行两个数[l,r] 数据保证 1<=l<=r<=n
Output
输出一行n个数字,表示原始序列经过m次变换后的结果
Sample Input
5 3
1 3
1 3
1 4
1 3
1 3
1 4
Sample Output
4 3 2 1 5
HINT
N,M<=100000
Source
带区间修改的平衡树裸题
区间操作的基本套路就是对于区间l,r,把l-1拧到根,r+1拧到根的右结点,然后显然l~r就都在r+1的左子树里,打个延迟什么的就很简单了,和线段树一样。
然后要下放标记
下放标记可以直接在kth里面下放,因为每次splay用到的所有节点都会在kth里访问一边(旋到根)
然而如果不是这样的题目的话最好splay之前pushup一下
为了方便一般在头尾分别插入俩结点。
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define inf 0x7f7f7f7f
#define maxn 200001
#define ls t[p].ch[0]
#define rs t[p].ch[1]
#define pa t[p].f
using namespace std;
int read()
{
char ch = getchar(); int x = 0, f = 1;
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
return x * f;
}
struct node {
int f, ch[2];
int v, size, rev;
node() {}
node(int val, int fa) {ch[1] = ch[0] = 0; size = 1; v = val; f = fa; rev = 0;}
}t[maxn]; int st[maxn], top, sz, root;
int wh(int p) {return t[pa].ch[1] == p;}
int newnode() {return top ? st[top--] : ++sz;}
int n, m;
void update(int p) {
t[p].size = t[ls].size + t[rs].size + 1;
}
void paint(int p)
{
t[p].rev ^= 1;
swap(ls, rs);
}
void pushdown(int p) {
if(t[p].rev) {
if(ls) paint(ls);
if(rs) paint(rs);
t[p].rev = 0;
}
}
void Rotate(int p) {
int f = pa, g = t[pa].f, c = wh(p);
if(g) t[g].ch[wh(f)] = p; t[p].f = g;
t[f].ch[c] = t[p].ch[c ^ 1]; if(t[f].ch[c]) t[t[f].ch[c]].f = f;
t[p].ch[c ^ 1] = f; t[f].f = p;
update(f);
}
void Splay(int p, int tar) {
for( ; pa != tar; Rotate(p))
if(t[pa].f != tar) Rotate(wh(pa) == wh(p) ? pa : p);
update(p);
if(!tar) root = p;
}
void Ins(int p, int val) {
int f = 0;
while(p) {f = p; p = rs;}
t[p = newnode()] = node(val, f);
if(f) t[f].ch[1] = p;
Splay(p, 0);
}
int Kth(int k) {
int p = root, lsize = 0;
while(p) {
pushdown(p);
int cur = lsize + t[ls].size;
if(k == cur + 1) return p;
if(k <= cur) p = ls;
else {
lsize = cur + 1;
p = rs;
}
}
return -1;
}
void Rever(int k1, int k2) {
int f = Kth(k1); Splay(f, 0);
int p = Kth(k2 + 2); Splay(p, f);
if(ls) paint(ls);
}
void print(int p)
{
pushdown(p);
if(ls) print(ls);
if(t[p].v != inf) cout<<t[p].v<<" ";
if(rs) print(rs);
}
void init()
{
root = 0; n = read(); m = read();
t[0] = node(0, 0); t[0].size = 0;
Ins(root, inf);
for(int i = 1;i <= n; ++i) Ins(root, i);
Ins(root, inf);
}
void solve()
{
for(int i = 1;i <= m; ++i)
{
int l = read(), r = read();
Rever(l, r);
}
}
int main()
{
init();
solve();
print(root);
puts("");
return 0;
}