题目背景
题目描述
您需要写一种数据结构(可参考题目标题),来维护一个有序数列。
其中需要提供以下操作:翻转一个区间,例如原有序序列是 5 4 3 2 15 4 3 2 1,翻转区间是 [2,4][2,4] 的话,结果是 5 2 3 4 15 2 3 4 1。
输入格式
第一行两个正整数 n,mn,m,表示序列长度与操作个数。序列中第 ii 项初始为 ii。
接下来 mm 行,每行两个正整数 l,rl,r,表示翻转的区间。
输出格式
输出一行 nn 个正整数,表示原始序列经过 mm 次变换后的结果。
输入输出样例
输入 #1
5 3 1 3 1 3 1 4
输出 #1
4 3 2 1 5
说明/提示
【数据范围】
对于 100\%100% 的数据,1 le n, m leq 1000001≤n,m≤100000,1 le l le r le n1≤l≤r≤n。
以前是用的splay
这次用的fhq treap 好写太多了
#include <bits/stdc++.h> using namespace std; const int maxn = 1000000 + 10; struct Tree{ int val, size, lc, rc, pri; bool tag; Tree(){ size = 0; } Tree(int val): val(val){ size = 1; lc = rc = 0; tag = false; pri = rand(); } }t[maxn]; int root = 0, tcnt = 0; inline void pushdown(int x){ if(t[x].tag){ swap(t[x].lc, t[x].rc); t[t[x].lc].tag ^= 1; t[t[x].rc].tag ^= 1; t[x].tag = false; } } inline void pushup(int x){ t[x].size = t[t[x].lc].size + t[t[x].rc].size + 1; } void split(int x, int &a, int &b, int k){ if(!x){ a = b = 0; return; } pushdown(x); if(k <= t[t[x].lc].size){ b = x; split(t[x].lc, a, t[b].lc, k); } else{ a = x; split(t[x].rc, t[a].rc, b, k - t[t[x].lc].size - 1); } pushup(x); } inline int newnode(int val){ t[++tcnt] = Tree(val); return tcnt; } void merge(int &x, int a, int b){ if(!a || !b){ x = a | b; return; } pushdown(a); pushdown(b); if(t[a].pri < t[b].pri){ x = a; merge(t[x].rc, t[a].rc, b); } else{ x = b; merge(t[x].lc, a, t[b].lc); } pushup(x); } void bl(int x){ if(!x) return; pushdown(x); bl(t[x].lc); cout << t[x].val << ' '; bl(t[x].rc); } int main(){ int n, m; cin >> n >> m; for(int i = 1; i <= n; i++){ merge(root, root, newnode(i)); } int l, r, a, b, c; for(int i = 1; i <= m; i++){ cin >> l >> r; split(root, a, b, l - 1); split(b, b, c, r - l + 1); t[b].tag = 1; merge(b, a, b); merge(root, b, c); } bl(root); putchar(' '); return 0; }