P3391 【模板】文艺平衡树FHQ treap

P3391 【模板】文艺平衡树(Splay)

题目背景

这是一道经典的Splay模板题——文艺平衡树。

题目描述

您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1

输入输出格式

输入格式:

 

第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2, \cdots n-1,n)(1,2,n1,n) m表示翻转操作次数

接下来m行每行两个数 [l,r][l,r] 数据保证 1 \leq l \leq r \leq n1lrn

 

输出格式:

 

输出一行n个数字,表示原始序列经过m次变换后的结果

 

输入输出样例

输入样例#1: 复制
5 3
1 3
1 3
1 4
输出样例#1: 复制
4 3 2 1 5

说明

 

code

 1 #include<cstdio>
 2 #include<algorithm>
 3 
 4 using namespace std;
 5 
 6 const int N = 500100;
 7 int ch[N][2],tag[N],val[N],siz[N],key[N];
 8 int tn,Root,n,m;
 9 
10 inline char nc() {
11     static char buf[100000],*p1 = buf,*p2 = buf;
12     return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2) ? EOF : *p1++;
13 }
14 inline int read() {
15     int x = 0,f = 1;char ch = nc();
16     for (; ch<'0'||ch>'9'; ch = nc()) 
17         if (ch=='-') f = -1;
18     for (; ch>='0'&&ch<='9'; ch = nc()) 
19         x = x*10+ch-'0';
20     return x * f;
21 }
22 inline void pushup(int x) {
23     siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + 1;
24 }
25 inline void pushdown(int x) {
26     if (tag[x]) {       
27         tag[ch[x][0]] ^= 1;tag[ch[x][1]] ^= 1;
28         swap(ch[x][0],ch[x][1]);
29         tag[x] ^= 1;
30     }
31 }
32 inline int makenode(int x) {
33     ++tn;siz[tn] = 1;val[tn] = x;key[tn] = rand();return tn;
34 }
35 int merge(int x,int y) {
36     if (!x || !y) return x + y;
37     pushdown(x);pushdown(y);
38     if (key[x] < key[y]) {
39         ch[x][1] = merge(ch[x][1],y);
40         pushup(x);return x;
41     }
42     else {
43         ch[y][0] = merge(x,ch[y][0]);
44         pushup(y);return y;
45     }
46 }
47 void split(int now,int k,int &x,int &y) {
48     if (!now) x = y = 0;
49     else {
50         pushdown(now);
51         if (k<=siz[ch[now][0]]) 
52             y = now,split(ch[now][0],k,x,ch[now][0]);
53         else 
54             x = now,split(ch[now][1],k-siz[ch[now][0]]-1,ch[now][1],y);
55         pushup(now);
56     }
57 }
58 inline void rever(int l,int r) {
59     int a,b,c,d;
60     split(Root,r,a,b);
61     split(a,l-1,c,d);
62     tag[d] ^= 1;
63     Root = merge(merge(c,d),b);    
64 }
65 void print(int x) {
66     if (!x) return ;
67     pushdown(x);
68     print(ch[x][0]);
69     printf("%d ",val[x]);
70     print(ch[x][1]);
71 }
72 int main() {
73     n = read(),m = read();
74     for (int i=1; i<=n; ++i) {
75         Root = merge(Root,makenode(i));
76     }
77     while (m--) {
78         int a = read(),b = read();
79         rever(a,b);
80     }
81     print(Root);
82     return 0;
83 }

 

网上学的另一种建树方法:

 1 int build(int l,int r)
 2 {
 3     if (l>r) return 0;
 4     int mid=(l+r)>>1,v=mid;
 5     int now=makenode(v);
 6     ch[now][0]=build(l,mid-1);
 7     ch[now][1]=build(mid+1,r);
 8     pushup(now);
 9     return now;
10 }
11 Root = build(1,n);

虽然可能不满足堆的性质,但是,堆在这个过程中只是调节树的平衡的,所以还是可以过的

 

板子的发展史。。。

 1 #include<cstdio>
 2 #include<algorithm>
 3 
 4 using namespace std;
 5 
 6 const int N = 500100;
 7 int ch[N][2],tag[N],val[N],siz[N],key[N];
 8 int tn,Root,n,m;
 9 
10 inline char nc() {
11     static char buf[100000],*p1 = buf,*p2 = buf;
12     return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2) ? EOF : *p1++;
13 }
14 inline int read() {
15     int x = 0,f = 1;char ch = nc();
16     for (; ch<'0'||ch>'9'; ch = nc()) 
17         if (ch=='-') f = -1;
18     for (; ch>='0'&&ch<='9'; ch = nc()) 
19         x = x*10+ch-'0';
20     return x * f;
21 }
22 inline void pushup(int x) {
23     siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + 1;
24 }
25 inline void pushdown(int x) {
26     if (tag[x]) {       
27         tag[ch[x][0]] ^= 1;tag[ch[x][1]] ^= 1;
28         swap(ch[x][0],ch[x][1]);
29         tag[x] ^= 1;
30     }
31 }
32 inline int makenode(int x) {
33     ++tn;siz[tn] = 1;val[tn] = x;key[tn] = rand();return tn;
34 }
35 int merge(int x,int y) {
36     if (!x || !y) return x + y;
37     if (key[x] < key[y]) {
38         pushdown(x);
39         ch[x][1] = merge(ch[x][1],y);
40         pushup(x);return x;
41     }
42     else {
43         pushdown(y);
44         ch[y][0] = merge(x,ch[y][0]);
45         pushup(y);return y;
46     }
47 }
48 void split(int now,int k,int &x,int &y) {
49     if (!now) x = y = 0;
50     else {
51         pushdown(now);
52         if (k<=siz[ch[now][0]]) 
53             y = now,split(ch[now][0],k,x,ch[now][0]);
54         else 
55             x = now,split(ch[now][1],k-siz[ch[now][0]]-1,ch[now][1],y);
56         pushup(now);
57     }
58 }
59 inline void rever(int l,int r) {
60     int a,b,c,d;
61     split(Root,r,a,b);
62     split(a,l-1,c,d);
63     tag[d] ^= 1;
64     Root = merge(merge(c,d),b);    
65 }
66 void print(int x) {
67     if (!x) return ;
68     pushdown(x);
69     print(ch[x][0]);
70     printf("%d ",val[x]);
71     print(ch[x][1]);
72 }
73 int main() {
74     n = read(),m = read();
75     for (int i=1; i<=n; ++i) {
76         Root = merge(Root,makenode(i));
77     }
78     while (m--) {
79         int a = read(),b = read();
80         rever(a,b);
81     }
82     print(Root);
83     return 0;
84 }
View Code

 

posted @ 2017-12-12 20:45  MJT12044  阅读(260)  评论(0编辑  收藏  举报