splay
给定一个长度为 n 的整数序列,初始时序列为 {1,2,…,n−1,n}。
序列中的位置从左到右依次标号为 1∼n。
我们用 [l,r] 来表示从位置 l 到位置 r 之间(包括两端点)的所有数字构成的子序列。
现在要对该序列进行 m 次操作,每次操作选定一个子序列 [l,r],并将该子序列中的所有数字进行翻转。
例如,对于现有序列 1 3 2 4 6 5 7
,如果某次操作选定翻转子序列为 [3,6],那么经过这次操作后序列变为 1 3 5 6 4 2 7
。
请你求出经过 m 次操作后的序列。
输入格式
第一行包含两个整数 n,m。
接下来 m 行,每行包含两个整数 l,r,用来描述一次操作。
输出格式
共一行,输出经过 m 次操作后的序列。
数据范围
1≤n,m≤105,
1≤l≤r≤n
输入样例:
6 3
2 4
1 5
3 5
输出样例:
5 2 1 4 3 6
#include<iostream> #include<algorithm> #include<cstring> using namespace std; const int N = 100010; struct Node { int s[2], p, v; int size,flag; void init(int _v, int _p) { v = _v, p = _p; size = 1; } }tr[N]; int root, idx,m,n; void pushup(int x) { tr[x].size = tr[tr[x].s[0]].size + tr[tr[x].s[1]].size + 1; } void pushdown(int x) { if(tr[x].flag){ swap(tr[x].s[0],tr[x].s[1]); tr[tr[x].s[0]].flag ^=1; tr[tr[x].s[1]].flag ^=1; tr[x].flag=0; } } void rotate(int x) // 旋转 { int y = tr[x].p, z = tr[y].p; int k = tr[y].s[1] == x; tr[z].s[tr[z].s[1] == y] = x, tr[x].p = z; tr[y].s[k] = tr[x].s[k ^ 1], tr[tr[x].s[k ^ 1]].p = y; tr[x].s[k ^ 1] = y, tr[y].p = x; pushup(y), pushup(x); } void splay(int x, int k) // splay操作 { while (tr[x].p != k) { int y = tr[x].p, z = tr[y].p; if (z != k) if ((tr[y].s[1] == x) ^ (tr[z].s[1] == y)) rotate(x); else rotate(y); rotate(x); } if (!k) root = x; } void insert(int v){ int u=root,p=0; while(u)p=u,u=tr[u].s[v>tr[u].v]; u=++idx; if (p) tr[p].s[v>tr[p].v]=u; tr[u].init(v,p); splay(u,0); } int get_k(int k) { int u = root; while (true) { pushdown(u); if (tr[tr[u].s[0]].size >= k) u = tr[u].s[0]; else if (tr[tr[u].s[0]].size + 1 == k) return u; else k -= tr[tr[u].s[0]].size + 1, u = tr[u].s[1]; } return -1; } void output(int u){ pushdown(u); if (tr[u].s[0]) output(tr[u].s[0]); if (tr[u].v>=1&&tr[u].v<=n) cout<<tr[u].v<<" "; if (tr[u].s[1]) output(tr[u].s[1]); } int main(){ scanf("%d%d", &n, &m);; for(int i=0;i<=n+1;i++) insert(i); while (m -- ){ int l,r; scanf("%d%d", &l, &r); l= get_k(l),r= get_k(r+2); splay(l,0), splay(r,l); tr[tr[r].s[0]].flag^=1; } output(root); return 0; }
给定一个长度为 n 的整数序列,初始时序列为 {1,2,…,n−1,n}。
序列中的位置从左到右依次标号为 1∼n。
我们用 [l,r] 来表示从位置 l 到位置 r 之间(包括两端点)的所有数字构成的子序列。
现在要对该序列进行 m 次操作,每次操作选定一个子序列 [l,r],并将该子序列中的所有数字进行翻转。
例如,对于现有序列 1 3 2 4 6 5 7
,如果某次操作选定翻转子序列为 [3,6],那么经过这次操作后序列变为 1 3 5 6 4 2 7
。
请你求出经过 m 次操作后的序列。
输入格式
第一行包含两个整数 n,m。
接下来 m 行,每行包含两个整数 l,r,用来描述一次操作。
输出格式
共一行,输出经过 m 次操作后的序列。
数据范围
1≤n,m≤105,
1≤l≤r≤n
输入样例:
6 3
2 4
1 5
3 5
输出样例:
5 2 1 4 3 6
本文在博客园发布,作者:limited_Infinite,转载请注明原文链接:https://www.cnblogs.com/limitedInfinite/p/14773685.html