洛谷 P3391文艺平衡树 【fhq_treap】

洛谷 P3391文艺平衡树

题意见链接。。。

题目明确说 splay模板题,我还是用了 fhq_treap(非旋treap)

对于此题来说,操作分为这么几块:

1、新加入节点,合并到基树中。

(要记录 size,val,pio(优先级,rand一下))

2、读入操作,开始翻转:

因为翻转的是区间,所以我们先把树按 r 分成两部分,然后再把左子树按 l-1 分成两部分,对应的需要操作的区间就是右子树。

用懒标记搞一下,再合并回去。

3、分离与合并操作:

分离:递归,如果 k 大于 size[left],那么就把左子树保留不变,递归右子树;左子树由 rt领头,右子树另到右子树中找节点。反之则同样。

合并:按优先级比较,pri[x]<pri[y] 则 x 的左子树保留,用 x 的右子树去和 y 合并。反之则用 y 的左子树和 x 合并。

4、上合与下传:

由于懒标记,所以要 pushdown,本题因为区间翻转,只需要记录被翻转几次,两次等于没有,抵消。

Pushup 也是线段树常规操作,更新完数据新的信息要上传到父亲节点更新。

总的来说就这样吧,待填坑。

贴代码:

 1 // 文艺平衡树 fhp_Treap
 2 // By YoungNeal
 3 #include<ctime>
 4 #include<cstdio>
 5 #include<cstdlib>
 6 #define N 100005
 7 
 8 int Root;
 9 int lazy[N];
10 int n,m,cnt;
11 int val[N],sze[N];
12 int ch[N][2],prio[N];
13 
14 void pushup(int o){
15     sze[o]=sze[ch[o][0]]+sze[ch[o][1]]+1;
16 }
17 
18 void pushdown(int o){
19     if(!lazy[o] or !o) return;
20     ch[o][0]^=ch[o][1]^=ch[o][0]^=ch[o][1];
21     lazy[ch[o][0]]^=1;
22     lazy[ch[o][1]]^=1;
23     lazy[o]=0;
24 }
25 
26 void split(int o,int k,int &x,int &y){
27     if(!o) x=y=0;
28     else{
29         pushdown(o);
30         if(k>sze[ch[o][0]]) x=o,split(ch[o][1],k-sze[ch[o][0]]-1,ch[o][1],y);
31         else y=o,split(ch[o][0],k,x,ch[o][0]);
32         pushup(o);
33     }
34 }
35 
36 int merge(int x,int y){
37     if(!x or !y) return x+y;
38     pushdown(x); pushdown(y);
39     if(prio[x]<prio[y]){
40         ch[x][1]=merge(ch[x][1],y);
41         pushup(x);
42         return x;
43     }
44     else{
45         ch[y][0]=merge(x,ch[y][0]);
46         pushup(y);
47         return y;
48     }
49 }
50 
51 int newnode(int v){
52     val[++cnt]=v;
53     sze[cnt]=1;
54     prio[cnt]=rand();
55     return cnt;
56 }
57 
58 void res(int l,int r){
59     int a,b,c,d;
60     split(Root,r,a,b);
61     split(a,l-1,c,d);
62     lazy[d]^=1;
63     Root=merge(merge(c,d),b);
64 }
65 
66 void dfs(int now){
67     if(!now) return;
68     pushdown(now);
69     dfs(ch[now][0]);
70     printf("%d ",val[now]);
71     dfs(ch[now][1]);
72 }
73 
74 signed main(){
75     srand(time(0));
76     scanf("%d%d",&n,&m);
77     for(int i=1;i<=n;i++)
78         Root=merge(Root,newnode(i));
79     //printf("Root=%d\n",Root);
80     for(int x,y,i=1;i<=m;i++){
81         scanf("%d%d",&x,&y);
82         res(x,y);
83         //printf("i=%d\n",i);
84         //dfs(Root);
85     }
86     //printf("Root=%d\n",Root);
87     dfs(Root);
88     return 0;
89 }
View Code

fightin fighting fighting

猜你喜欢

转载自www.cnblogs.com/Frank-King/p/9860642.html