【Splay】[SGU 187]Twist and whirl - want to cheat
这道题真是我见过的最坑的平衡树的题目。。。。
time limit per test: 0.25 sec.
memory limit per test: 4096 KB
这个也太小了吧!
题目大意就是有一个数列一开始是1-n然后给出l, r每次把当前第l到第r个逆序,然后输出n<=130000 m<=2000
首先我写了一个传统的东西,然后在24组TLE然后,从指针的Splay转换成数组的Splay然后发现依然过不了,分析了一下复杂度,发现如果用传统的Splay的Insert虽然理论复杂度很低,但是相对于这道题,Insert完了之后整个树就退化成了一条链,然后根据这个题目的Insert特殊优化线段树的构建方法建树就可以A了
然后就是一开始整棵树里面有无限小和无限大,然后每次翻转的时候把l-1放到根节点,把r+1放到根节点的右儿子,然后给根节点的右儿子的左儿子打标记,然后要对该节点子树操作的时候向下传递标记,然后交换左右节点就行了
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int MAXN = 130013;
int ch[MAXN][2], fa[MAXN], val[MAXN], size[MAXN], ecnt, root;
bool rev[MAXN];
inline void Update(int x){size[x] = size[ch[x][0]] + size[ch[x][1]] + 1;}
inline void push_up(int u){
if(rev[u]){
swap(ch[u][0], ch[u][1]);
rev[ch[u][0]] ^= 1;
rev[ch[u][1]] ^= 1;
rev[u] = 0;
}
}
inline void Rotate(int x, int d){
int y = fa[x];
ch[y][!d] = ch[x][d];
fa[x] = fa[y];
if(ch[x][d]!=0)
fa[ch[x][d]] = y;
if(fa[y]!=0)
ch[fa[y]][y == ch[fa[y]][1]] = x;
fa[y] = x;
ch[x][d] = y;
if(y == root) root = x;
Update(y);
}
void Splay(int, int);
inline void Insert(int &now, int l, int r, int f){
if(l > r) return ;
now = ++ecnt;
int mid = (l + r) >> 1;
val[now] = mid, fa[now] = f;
Insert(ch[now][0], l, mid-1, now);
Insert(ch[now][1], mid+1, r, now);
Update(now);
}
int f1, f2;
inline void Splay(int x,int y){
while(fa[x] != y){
f1 = fa[x]; f2 = fa[f1];
if(f2 == y){
push_up(f1);
push_up(x);
if(x == ch[f1][0]) Rotate(x,1);
else Rotate(x,0);
}else{
push_up(f2);
push_up(f1);
push_up(x);
if(f1 == ch[f2][0]){
if(x == ch[f1][0]){
Rotate(f1, 1);
Rotate(x, 1);
}else{
Rotate(x, 0);
Rotate(x, 1);
}
}else{
if(x == ch[f1][0]){
Rotate(x, 1);
Rotate(x, 0);
}else{
Rotate(f1, 0);
Rotate(x, 0);
}
}
}
Update(x);
}
}
inline int Find_Rank(int va){
int ret = root;
while(true){
push_up(ret);
if(size[ch[ret][0]]+1 == va)
break;
if(va > size[ch[ret][0]])
va -= size[ch[ret][0]] + 1, ret = ch[ret][1];
else
ret = ch[ret][0];
}
return ret;
}
int main(){
int n, mode, modep, t, p, q;
scanf("%d",&t);
Insert(root, 0, t+1, 0);
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d%d", &mode, &modep);
p = Find_Rank(mode);
q = Find_Rank(modep+2);
Splay(p, 0);
Splay(q, p);
rev[ch[q][0]] ^= 1;
}
printf("%d", val[Find_Rank(2)]);
for(int i=2;i<=t;i++)
printf(" %d", val[Find_Rank(i+1)]);
return 0;
}