题意:给定初始的n个数的排列,然后把[a,b]区间的数取出来反转一下放到最后,就是left,mid,right,转成:left,right,mid。
利用slpay的把任意一个特定点旋转到根节点的思路,再利用线段树懒惰标记的思路,该节点的子树需要反转,flip置为1,否则为0,然后每次旋转时(事实上是每次用到该节点,就要pushdown,maintain,这点想清楚)再执行pushdown,maintain。
然后就解决了,有点出乎我意料的快。。我以为写出来会调很久。。呵呵。
其中各种指针操作,有些是&引用,有些没有&引用,这点想清楚。确实很巧妙,避免了许多指针回传和修改。
#include <fstream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
struct Node {
Node* ch[2];
int v;//value
int rank;// current tree's position
int s;//sum
int flip;//rotate flag
int cmp(int x) const {
if (x==rank) return -1;
return x<rank? 0 : 1;
}
void pushdown(){
if (flip) {
flip=0;
swap(ch[0],ch[1]);
if(ch[0]!=NULL) ch[0]->flip = !ch[0]->flip;
if(ch[1]!=NULL) ch[1]->flip = !ch[1]->flip;
}
}
void maintain(){
s=1;
rank=1;
if (ch[0]!=NULL) {
s+=ch[0]->s;
rank+=ch[0]->s;
}
if (ch[1]!=NULL) s+=ch[1]->s;
}
};
void dfs(Node* o) {
o->pushdown();
if (o->ch[0]!=NULL) dfs(o->ch[0]);
if (o->v) printf("%d\n",o->v);
if (o->ch[1]!=NULL) dfs(o->ch[1]);
}
Node* init(int l,int r)
{
Node* p;
int mid=(l+r)>>1;
p=(Node*)malloc(sizeof(Node));
p->s = r-l+1;
p->rank = mid-l+1;
p->v = mid;
p->flip = 0;
p->ch[0] = p->ch[1] =NULL;
if (mid-1>=l) p->ch[0]=init(l,mid-1);
if (mid+1<=r) p->ch[1]=init(mid+1,r);
return p;
}
void rotate(Node* &o,int d)
{
Node* k = o->ch[d^1];
o->ch[d^1] = k->ch[d];
k->ch[d] = o;
o->maintain();
k->maintain();
o = k;
}
void splay(Node* &o,int k) {
//correct
o->pushdown();
o->maintain();
int d= o->cmp(k);
if (d==1) k -= o->rank;
if (d!=-1) {
Node* p = o->ch[d];
//correct
p->pushdown();
p->maintain();
int d2 = p->cmp(k);
int k2 = (d2==0 ? k : k-p->rank);
if (d2!=-1) {
splay(p->ch[d2],k2);
if (d==d2) rotate(o,d^1);
else rotate(o->ch[d], d);
}
rotate(o,d^1);
}
}
void split(Node* o,int k,Node* &left,Node* &right)
{
splay(o,k);
left = o;
right = o->ch[1];
o->ch[1] = NULL;
left->maintain();
}
Node* merge(Node* left,Node* right)
{
splay(left, left->s);
left->ch[1] = right;
left->maintain();
return left;
}
int main()
{
freopen("1.in","r",stdin);
int n, m;
scanf("%d%d",&n,&m);
Node* root;
root=init(0,n);
while (m--) {
//dfs(root);
int a, b;
scanf("%d%d",&a,&b);
Node* left, *mid, *right, *o;
split(root, a, left, o);
split(o, b-a+1, mid, right);
mid->flip ^=1;
root= merge(merge(left,right),mid);
}
//print
dfs(root);
return 0;
}