洛谷P3391 【模板】文艺平衡树
题目描述
您需要写一种数据结构(可参考题目标题),来维护一个有序数列。
其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4] 的话,结果是5 2 3 4 1。
输入格式
第一行两个正整数n,m,表示序列长度与操作个数。序列中第i项初始为i。
接下来m行,每行两个正整数l,r,表示翻转的区间。
输出格式
输出一行n个正整数,表示原始序列经过m次变换后的结果。
输入输出样例
输入 #1
5 3 1 3 1 3 1 4
输出 #1
4 3 2 1 5
说明/提示
【数据范围】
对于100% 的数据,1≤n,m≤100000,1≤l≤r≤n。
思路:明显平衡树维护区间修改,接近于板子题
值得一说的是,fhq-treap在维护序列时,void split(int p,int x,int &l,int &r)的意思不再是分离<=k和>k的两棵树
而是变为了 将序列p的前x个元素分离出来形成一棵新fhq-treap的l子树,另外的一部分形成另一颗 fhq-treap的r 子树
所以,split你会发现写法像极了前面的普通平衡树的getnum函数
而且新增了懒标记(线段树诈尸!)用来标记区间是否被翻转了,
还有pushdown也是不同于普通平衡树,显然是懒标记使用的后果
仍reverse等,但由于这是这道题中的写法,别的题中不一定适用,此处不多赘述
#include<bits/stdc++.h> using namespace std; struct node{ int l,r,key,val,si; bool flag; }tr[200010]; int n,m,idx,dl,dr,tmp,rt; int getrand(int x){ tr[++idx].key = x; tr[idx].val = rand(); tr[idx].si = 1; return idx; } void pushup(int p){ tr[p].si = tr[tr[p].l].si+tr[tr[p].r].si+1; } void pushdown(int p){ if(tr[p].flag){ tr[tr[p].l].flag^=1;//用异或是因为翻转两次即可不用翻转 tr[tr[p].r].flag^=1; swap(tr[p].l,tr[p].r); tr[p].flag = 0; } } void split(int p,int x,int &l,int &r){ if(!p){ l = r = 0; return ; } pushdown(p); int u = tr[tr[p].l].si+1; if(u<=x){ l = p; split(tr[l].r,x-u,tr[l].r,r); pushup(l); }else{ r = p; split(tr[r].l,x,l,tr[r].l); pushup(r); } } int merge(int l,int r){ if(!l||!r) return l|r; pushdown(l); pushdown(r); if(tr[l].val<=tr[r].val){ tr[l].r = merge(tr[l].r,r); pushup(l); return l; }else{ tr[r].l = merge(l,tr[r].l); pushup(r); return r; } }void reverse(int l,int r){ int p1 = 0,p2 = 0,p3 = 0,p4 = 0; split(rt,l-1,p1,p2); split(p2,r-l+1,p3,p4); tr[p3].flag^=1; p2 = merge(p3,p4); rt = merge(p1,p2); } void printres(int p){ pushdown(p); if(tr[p].l) printres(tr[p].l); printf("%d ",tr[p].key); if(tr[p].r) printres(tr[p].r); } int main(){ scanf("%d%d",&n,&m); for(int i = 1;i<=n;i++){ split(rt,i-1,dl,dr); rt = merge(merge(dl,getrand(i)),dr); } int x,y; while(m--){ scanf("%d%d",&x,&y); reverse(x,y); } printres(rt); return 0; }
综上所述,我是蒟蒻
2022-10-28 17:46:37
梦与现实间挣扎着,所求为何
你可以借走我的文章,但你借不走我的智慧 虽然我是傻逼本文来自博客园,作者:cztq,转载请注明原文链接:https://www.cnblogs.com/cztq/p/16836895.html