题意:有N个点,初始从1至N排列,现在我们对数轴上第l到第r区间内的所有的点进行翻转操作,问经过M次操作之后,数轴上的数的排列情况。
很明显的,我们可以发现,这是一个Splay的操作,但是只有N个元素显得比较的麻烦了(细节+++),于是,我给首尾各加一个值,现在初始数轴变成了(1~N+2)。那么,当我们要把[L,R]区间拉出来的时候,实际上就是将(L)这个点拉成根节点,然后将(R+2)这个位置上的点拉到(L)的下面,那么(R+2)的左子树就是(L+1~R+1)的区间了,也正是对应我们的操作的([l,r])区间的。
然后,这里有需要注意的地方,我们在进行Splay的时候,切记要先进行pushdown,先从将根到目前操作节点的lazy都pushdown了,不然有可能当我们将其中一个节点操作的时候,拉出子树的时候,还没有继承祖先节点的信息,容易造成数据缺失。
#include <iostream> #include <cstdio> #include <cmath> #include <string> #include <cstring> #include <algorithm> #include <limits> #include <vector> #include <stack> #include <queue> #include <set> #include <map> #include <bitset> #include <unordered_map> #include <unordered_set> #define lowbit(x) ( x&(-x) ) #define pi 3.141592653589793 #define e 2.718281828459045 #define INF 0x3f3f3f3f #define HalF (l + r)>>1 #define lsn rt<<1 #define rsn rt<<1|1 #define Lson lsn, l, mid #define Rson rsn, mid+1, r #define QL Lson, ql, qr #define QR Rson, ql, qr #define myself rt, l, r #define pii pair<int, int> #define MP(a, b) make_pair(a, b) using namespace std; typedef unsigned long long ull; typedef unsigned int uit; typedef long long ll; const int maxN = 1e5 + 7; int N, M, root; bool rr[maxN] = {0}; struct node { int ff, ch[2], siz; node() { ff = ch[0] = ch[1] = 0; siz = 0; } void init(int fa) { ff = fa; ch[0] = ch[1] = 0; siz = 1; } } t[maxN]; void pushup(int x) { t[x].siz = 1; if(t[x].ch[0]) t[x].siz += t[t[x].ch[0]].siz; if(t[x].ch[1]) t[x].siz += t[t[x].ch[1]].siz; } void pushdown(int x) { if(rr[x]) { rr[t[x].ch[0]] ^= 1; rr[t[x].ch[1]] ^= 1; swap(t[x].ch[0], t[x].ch[1]); rr[x] = 0; } } void Rotate(int x) { int y = t[x].ff, z = t[y].ff; int k = t[y].ch[1] == x; t[z].ch[t[z].ch[1] == y] = x; t[x].ff = z; t[y].ch[k] = t[x].ch[k ^ 1]; t[t[x].ch[k ^ 1]].ff = y; t[x].ch[k ^ 1] = y; t[y].ff = x; pushup(y); pushup(x); } int Stap[maxN], Stop; void Splay(int x, int goal) { Stop = 0; int y = x, z; while(y) { Stap[++ Stop] = y; y = t[y].ff; } while(Stop) pushdown(Stap[Stop --]); while(t[x].ff != goal) { y = t[x].ff; z = t[y].ff; if(z != goal) (t[z].ch[0] == y) ^ (t[y].ch[0] == x) ? Rotate(x) : Rotate(y); Rotate(x); } if(!goal) root = x; } int build(int fa, int l, int r) { if(l > r) return 0; int mid = HalF; t[mid].init(fa); t[mid].ch[0] = build(mid, l, mid - 1); t[mid].ch[1] = build(mid, mid + 1, r); pushup(mid); return mid; } int kth(int k) { int u = root; if(t[u].siz < k) return 0; while(true) { pushdown(u); int v = t[u].ch[0]; if(k > t[v].siz + 1) { k -= t[v].siz + 1; u = t[u].ch[1]; } else { if(t[v].siz >= k) u = v; else return u; } } } void change(int l, int r) { int len = r - l + 1; int x = kth(l), y = kth(r + 2); Splay(x, 0); Splay(y, x); int u = t[y].ch[0]; t[y].ch[0] = 0; t[u].ff = 0; pushup(y); pushup(x); rr[u] ^= 1; x = kth(N - len + 1); Splay(x, 0); y = t[x].ch[1]; t[y].ch[0] = u; t[u].ff = y; pushup(y); pushup(x); } int ans[maxN], tot; void query(int x) { pushdown(x); if(t[x].ch[0]) query(t[x].ch[0]); if(x >= 2 && x <= N + 1) ans[++ tot] = x - 1; if(t[x].ch[1]) query(t[x].ch[1]); } void Prit() { query(root); for(int i = 1; i <= N; i ++) printf("%d ", ans[i]); tot = 0; } int main() { scanf("%d%d", &N, &M); root = build(0, 1, N + 2); for(int i = 1, l, r; i <= M; i ++) { scanf("%d%d", &l, &r); change(l, r); } Prit(); return 0; }