bzoj 1500 [NOI 2005] 维修数列
2015-04-22 00:10
471 查看
题目大意不多说了
貌似每个苦逼的acmer都要做一下这个splay树的模版题目吧
还是有很多操作的,估计够以后当模版了。。。。
貌似每个苦逼的acmer都要做一下这个splay树的模版题目吧
还是有很多操作的,估计够以后当模版了。。。。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> using namespace std; const int N = 1000010; const int INF = 0x3f3f3f3f; #define ls ch[x][0] #define rs ch[x][1] struct SplayTree{ int ch [2] , pre ; int ml , mr , mm ; //区间最大 int val , sz , sum , size , rt; int rev , to ; // lazy标记 int del , top; //内部保存删除的数的位置,然后可以从其中提取位置给新进入的元素 int a ; void push_up(int x) { sz[x] = sz[ls]+sz[rs]+1; sum[x] = sum[ls]+sum[rs]+val[x]; /*********************/ ml[x] = max(ml[ls] , sum[ls]+val[x]+max(ml[rs] , 0)); mr[x] = max(mr[rs] , sum[rs]+val[x]+max(mr[ls] , 0)); mm[x] = max(mm[ls] , max(mm[rs] , max(ml[rs],0)+max(mr[ls],0)+val[x])); /*********************/ } void push_down(int x) { if(rev[x]){ if(ls){ rev[ls]^=1 ; swap(ml[ls] , mr[ls]); } if(rs){ rev[rs]^=1 ; swap(ml[rs] , mr[rs]); } swap(ls , rs); rev[x] = 0; } /**to[x]的初始化要注意**/ if(to[x]!=-INF){ if(ls){ sum[ls] = sz[ls]*to[x]; ml[ls] = mr[ls] = mm[ls] = max(sum[ls] , to[x]); val[ls] = to[ls] = to[x]; } if(rs){ sum[rs] = sz[rs]*to[x]; ml[rs] = mr[rs] = mm[rs] = max(sum[rs] , to[x]); val[rs] = to[rs] = to[x]; } to[x] = -INF; } } void newNode(int &x , int fa , int v) { if(top != -1) x = del[top--]; else x = ++size; ch[x][0] = ch[x][1] = 0; pre[x] = fa; val[x] = v , sz[x] = 1; sum[x] = ml[x] = mr[x] = mm[x] = val[x]; rev[x] = 0 , to[x] = -INF; } void build(int &x , int l , int r , int fa) { if(l>r) return; int m=(l+r)>>1; newNode(x , fa , a[m]); build(ls , l , m-1 , x); build(rs , m+1 , r , x); push_up(x); } void init(int n) { /*****因为所有点的最终叶子节点都下标设为了0,所以0上的数据要不影响整棵树*****/ sz[0] = sum[0] = ch[0][0] = ch[0][1] = val[0] = pre[0] = 0; to[0] = ml[0] = mr[0] = mm[0] = -INF; rev[0] = 0; top = -1 , rt = size = 0; newNode(rt , 0 , -INF); newNode(ch[rt][1] , rt , -INF); build(ch[ch[rt][1]][0] , 1 , n , ch[rt][1]); push_up(ch[rt][1]); push_up(rt); } void Rotate(int x , int f) { int y=pre[x] , z=pre[y]; /**y要旋转到下方,下传lazy标记**/ push_down(y); ch[y][!f] = ch[x][f] , pre[ch[x][f]] = y; ch[x][f] = y , pre[y] = x; ch[z][ch[z][1]==y] = x , pre[x]=z; push_up(y); push_up(x); } void Splay(int x , int goal) { while(pre[x] != goal){ if(pre[pre[x]] == goal) Rotate(x , ch[pre[x]][0]==x); else{ int y = pre[x] , z = pre[y]; int f = ch[z][0] == y; if(ch[y][f] == x) Rotate(x , !f); else Rotate(y,f); Rotate(x , f); } } push_up(x); if(goal == 0) rt = x; } int Select(int pos) { int x = rt; push_down(x); while(sz[ls]+1 != pos){ if(sz[ls]+1>pos) x=ls; else{ pos = pos-sz[ls]-1; x = rs; } push_down(x); } return x; } /***从pos位置之后插入cnt个值***/ void Insert(int pos , int cnt) { int x = Select(pos); Splay(x , 0); int y = Select(pos+1); Splay(y , x); build(ch[y][0] , 1 , cnt , y); /***这里build将a[1~cnt]插入到splay树中,要push_up更新***/ push_up(y); push_up(x); } /***回收被删除的数的位置***/ void Recycle(int x) { if(x){ del[++top]=x; Recycle(ls); Recycle(rs); } } void Delete(int s , int t) { int x = Select(s-1) , y = Select(t+1); Splay(x , 0) , Splay(y , x); Recycle(ch[y][0]); ch[y][0] = 0; /***这里y的左子树删除,明显子树数据改变,所以要重新push_up更新数据***/ push_up(y); push_up(x); } /****将s~t区间内的所有值都修改为v****/ void update(int s , int t , int v) { int x = Select(s-1) , y = Select(t+1); Splay(x , 0) , Splay(y , x); int ptr = ch[y][0]; to[ptr]=v; val[ptr]=v; sum[ptr]=v*sz[ptr]; ml[ptr] = mr[ptr] = mm[ptr] = max(sum[ptr] , v); return ; } void Reverse(int s , int t) { int x = Select(s-1) , y = Select(t+1); Splay(x , 0) , Splay(y , x); int ptr = ch[y][0]; rev[ptr]^=1; swap(ml[ptr] , mr[ptr]); } int querySum(int s , int t) { int x = Select(s-1) , y = Select(t+1); // cout<<"x: "<<x<<" y: "<<y<<endl; Splay(x , 0) , Splay(y , x); return sum[ch[y][0]]; } int queryMax() { int x = Select(1) , y = Select(sz[rt]); Splay(x , 0) , Splay(y , x); return mm[ch[y][0]]; } }spt; int main() { // freopen("a.in" , "r" , stdin); int n , m; char str[20] ; int s , t , v , pos , k; while(~scanf("%d%d" , &n , &m)) { for(int i=1 ; i<=n ; i++) scanf("%d" , &spt.a[i]); spt.init(n); /* for(int i=0 ; i<=spt.size ; i++){ 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; }*/ for(int i=0 ; i<m ; i++){ scanf("%s" , str); if(str[0] == 'I'){ scanf("%d%d" , &pos , &k); for(int i=1 ; i<=k ; i++) scanf("%d" , &spt.a[i]); spt.Insert(pos+1 , k); } else if(str[0]=='D'){ scanf("%d%d" , &pos , &k); spt.Delete(pos+1 , pos+k); } else if(str[0] == 'M' && str[2] == 'K'){ scanf("%d%d%d" , &pos , &k , &v); spt.update(pos+1 , pos+k , v); } else if(str[0] == 'R'){ scanf("%d%d" , &pos , &k); spt.Reverse(pos+1 , pos+k); } else if(str[0] == 'G'){ scanf("%d%d" , &pos , &k); printf("%d\n" , spt.querySum(pos+1 , pos+k)); } else{ /****这里不能直接用spt.mm[rt]作为答案,因为为了方便查询, 我们增加了两个不包含在本身数组的点,直接spt.mm[rt]会把这两个点也算进来***/ printf("%d\n" , spt.queryMax()); } } } return 0; }
相关文章推荐
- BZOJ 1500 NOI 2005 维修数列 Splay
- [BZOJ 1500][NOI2005]维修数列(Splay)
- BZOJ 1500 【NOI2005 D1T2】 维修数列 Splay
- bzoj:1500: [NOI2005]维修数列
- [BZOJ1500][NOI2005]维修数列
- BZOJ1500: [NOI2005]维修数列 [splay序列操作]【学习笔记】
- 【bzoj1500】[NOI2005]维修数列
- _bzoj1500 [NOI2005]维修数列【真·Splay】
- [BZOJ1500][NOI2005]维修数列(平衡树)
- 【bzoj1500】[NOI2005]维修数列 Splay
- 【平衡树维护序列】BZOJ1500(NOI2005)[维修数列]题解
- bzoj1500 [NOI2005]维修数列解题报告
- 【bzoj1500】[NOI2005]维修数列 Splay
- BZOJ 1500[NOI2005] 维修数列
- BZOJ_1500_[NOI2005]维修数列_splay
- BZOJ 1500: [NOI2005]维修数列
- BZOJ 1500: [NOI2005]维修数列 (splay tree)
- 【BZOJ1500】[NOI2005]维修数列 Splay
- Bzoj1500 [NOI2005]维修数列
- [bzoj1500][NOI2005]维修数列