题目大意不多说了
貌似每个苦逼的acmer都要做一下这个splay树的模版题目吧
还是有很多操作的,估计够以后当模版了。。。。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 7 using namespace std; 8 const int N = 1000010; 9 const int INF = 0x3f3f3f3f; 10 #define ls ch[x][0] 11 #define rs ch[x][1] 12 13 struct SplayTree{ 14 int ch[N][2] , pre[N]; 15 int ml[N] , mr[N] , mm[N]; //区间最大 16 int val[N] , sz[N] , sum[N] , size , rt; 17 int rev[N] , to[N]; // lazy标记 18 int del[N] , top; //内部保存删除的数的位置,然后可以从其中提取位置给新进入的元素 19 int a[N]; 20 21 void push_up(int x) 22 { 23 sz[x] = sz[ls]+sz[rs]+1; 24 sum[x] = sum[ls]+sum[rs]+val[x]; 25 /*********************/ 26 ml[x] = max(ml[ls] , sum[ls]+val[x]+max(ml[rs] , 0)); 27 mr[x] = max(mr[rs] , sum[rs]+val[x]+max(mr[ls] , 0)); 28 mm[x] = max(mm[ls] , max(mm[rs] , max(ml[rs],0)+max(mr[ls],0)+val[x])); 29 /*********************/ 30 } 31 32 void push_down(int x) 33 { 34 if(rev[x]){ 35 if(ls){ 36 rev[ls]^=1 ; 37 swap(ml[ls] , mr[ls]); 38 } 39 if(rs){ 40 rev[rs]^=1 ; 41 swap(ml[rs] , mr[rs]); 42 } 43 swap(ls , rs); 44 rev[x] = 0; 45 } 46 /**to[x]的初始化要注意**/ 47 if(to[x]!=-INF){ 48 if(ls){ 49 sum[ls] = sz[ls]*to[x]; 50 ml[ls] = mr[ls] = mm[ls] = max(sum[ls] , to[x]); 51 val[ls] = to[ls] = to[x]; 52 } 53 if(rs){ 54 sum[rs] = sz[rs]*to[x]; 55 ml[rs] = mr[rs] = mm[rs] = max(sum[rs] , to[x]); 56 val[rs] = to[rs] = to[x]; 57 } 58 to[x] = -INF; 59 } 60 } 61 62 void newNode(int &x , int fa , int v) 63 { 64 if(top != -1) 65 x = del[top--]; 66 else x = ++size; 67 ch[x][0] = ch[x][1] = 0; 68 pre[x] = fa; 69 val[x] = v , sz[x] = 1; 70 sum[x] = ml[x] = mr[x] = mm[x] = val[x]; 71 rev[x] = 0 , to[x] = -INF; 72 } 73 74 void build(int &x , int l , int r , int fa) 75 { 76 if(l>r) return; 77 int m=(l+r)>>1; 78 newNode(x , fa , a[m]); 79 build(ls , l , m-1 , x); 80 build(rs , m+1 , r , x); 81 push_up(x); 82 } 83 84 void init(int n) 85 { 86 /*****因为所有点的最终叶子节点都下标设为了0,所以0上的数据要不影响整棵树*****/ 87 sz[0] = sum[0] = ch[0][0] = ch[0][1] = val[0] = pre[0] = 0; 88 to[0] = ml[0] = mr[0] = mm[0] = -INF; 89 rev[0] = 0; 90 top = -1 , rt = size = 0; 91 newNode(rt , 0 , -INF); 92 newNode(ch[rt][1] , rt , -INF); 93 build(ch[ch[rt][1]][0] , 1 , n , ch[rt][1]); 94 push_up(ch[rt][1]); 95 push_up(rt); 96 } 97 98 void Rotate(int x , int f) 99 { 100 int y=pre[x] , z=pre[y]; 101 /**y要旋转到下方,下传lazy标记**/ 102 push_down(y); 103 ch[y][!f] = ch[x][f] , pre[ch[x][f]] = y; 104 ch[x][f] = y , pre[y] = x; 105 ch[z][ch[z][1]==y] = x , pre[x]=z; 106 push_up(y); 107 push_up(x); 108 } 109 110 void Splay(int x , int goal) 111 { 112 while(pre[x] != goal){ 113 if(pre[pre[x]] == goal) Rotate(x , ch[pre[x]][0]==x); 114 else{ 115 int y = pre[x] , z = pre[y]; 116 int f = ch[z][0] == y; 117 if(ch[y][f] == x) Rotate(x , !f); 118 else Rotate(y,f); 119 Rotate(x , f); 120 } 121 } 122 push_up(x); 123 if(goal == 0) rt = x; 124 } 125 126 int Select(int pos) 127 { 128 int x = rt; 129 push_down(x); 130 while(sz[ls]+1 != pos){ 131 if(sz[ls]+1>pos) x=ls; 132 else{ 133 pos = pos-sz[ls]-1; 134 x = rs; 135 } 136 push_down(x); 137 } 138 return x; 139 } 140 /***从pos位置之后插入cnt个值***/ 141 void Insert(int pos , int cnt) 142 { 143 int x = Select(pos); 144 Splay(x , 0); 145 int y = Select(pos+1); 146 Splay(y , x); 147 build(ch[y][0] , 1 , cnt , y); 148 /***这里build将a[1~cnt]插入到splay树中,要push_up更新***/ 149 push_up(y); 150 push_up(x); 151 } 152 /***回收被删除的数的位置***/ 153 void Recycle(int x) 154 { 155 if(x){ 156 del[++top]=x; 157 Recycle(ls); 158 Recycle(rs); 159 } 160 } 161 162 void Delete(int s , int t) 163 { 164 int x = Select(s-1) , y = Select(t+1); 165 Splay(x , 0) , Splay(y , x); 166 Recycle(ch[y][0]); 167 ch[y][0] = 0; 168 /***这里y的左子树删除,明显子树数据改变,所以要重新push_up更新数据***/ 169 push_up(y); 170 push_up(x); 171 } 172 /****将s~t区间内的所有值都修改为v****/ 173 void update(int s , int t , int v) 174 { 175 int x = Select(s-1) , y = Select(t+1); 176 Splay(x , 0) , Splay(y , x); 177 int ptr = ch[y][0]; 178 to[ptr]=v; 179 val[ptr]=v; 180 sum[ptr]=v*sz[ptr]; 181 ml[ptr] = mr[ptr] = mm[ptr] = max(sum[ptr] , v); 182 return ; 183 } 184 185 void Reverse(int s , int t) 186 { 187 int x = Select(s-1) , y = Select(t+1); 188 Splay(x , 0) , Splay(y , x); 189 int ptr = ch[y][0]; 190 rev[ptr]^=1; 191 swap(ml[ptr] , mr[ptr]); 192 } 193 194 int querySum(int s , int t) 195 { 196 int x = Select(s-1) , y = Select(t+1); 197 // cout<<"x: "<<x<<" y: "<<y<<endl; 198 Splay(x , 0) , Splay(y , x); 199 return sum[ch[y][0]]; 200 } 201 202 int queryMax() 203 { 204 int x = Select(1) , y = Select(sz[rt]); 205 Splay(x , 0) , Splay(y , x); 206 return mm[ch[y][0]]; 207 } 208 }spt; 209 int main() 210 { 211 // freopen("a.in" , "r" , stdin); 212 int n , m; 213 char str[20] ; 214 int s , t , v , pos , k; 215 while(~scanf("%d%d" , &n , &m)) 216 { 217 for(int i=1 ; i<=n ; i++) scanf("%d" , &spt.a[i]); 218 spt.init(n); 219 /* 220 for(int i=0 ; i<=spt.size ; i++){ 221 cout<<"i: "<<i<<" sum: "<<spt.sum[i]<<" l: "<<spt.ch[i][0]<<" lv: "<<spt.val[spt.ch[i][0]]<<" r: "<<spt.ch[i][1]<<" rv: "<<spt.val[spt.ch[i][1]]<<endl; 222 }*/ 223 for(int i=0 ; i<m ; i++){ 224 scanf("%s" , str); 225 if(str[0] == ‘I‘){ 226 scanf("%d%d" , &pos , &k); 227 for(int i=1 ; i<=k ; i++) scanf("%d" , &spt.a[i]); 228 spt.Insert(pos+1 , k); 229 } 230 else if(str[0]==‘D‘){ 231 scanf("%d%d" , &pos , &k); 232 spt.Delete(pos+1 , pos+k); 233 } 234 else if(str[0] == ‘M‘ && str[2] == ‘K‘){ 235 scanf("%d%d%d" , &pos , &k , &v); 236 spt.update(pos+1 , pos+k , v); 237 } 238 else if(str[0] == ‘R‘){ 239 scanf("%d%d" , &pos , &k); 240 spt.Reverse(pos+1 , pos+k); 241 } 242 else if(str[0] == ‘G‘){ 243 scanf("%d%d" , &pos , &k); 244 printf("%d\n" , spt.querySum(pos+1 , pos+k)); 245 } 246 else{ 247 /****这里不能直接用spt.mm[rt]作为答案,因为为了方便查询, 248 我们增加了两个不包含在本身数组的点,直接spt.mm[rt]会把这两个点也算进来***/ 249 printf("%d\n" , spt.queryMax()); 250 } 251 } 252 } 253 return 0; 254 }
时间: 2024-11-12 09:16:29