[NOI2005] 维护数列
[NOI2005] 维护数列
题目
请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格)
操作编号
输入文件中的格式
说明
1. 插入
INSERT_posi_tot_c1_c2_..._ctot
在当前数列的第 posi 个数字后插入 tot
个数字:c1, c2, …, ctot;若在数列首插
入,则 posi 为 0
2. 删除
DELETE_posi_tot
从当前数列的第 posi 个数字开始连续
删除 tot 个数字
3. 修改
MAKE-SAME_posi_tot_c
将当前数列的第 posi 个数字开始的连
续 tot 个数字统一修改为 c
4. 翻转
REVERSE_posi_tot
取出从当前数列的第 posi 个数字开始
的 tot 个数字,翻转后放入原来的位置
5. 求和
GET-SUM_posi_tot
计算从当前数列开始的第 posi 个数字
开始的 tot 个数字的和并输出
6. 求和最
大的子列
MAX-SUM
求出当前数列中和最大的一段子列,
并输出最大和
INPUT
输入文件的第 1 行包含两个数 N 和 M,N 表示初始时数列中数的个数,M表示要进行的操作数目。
第 2 行包含 N 个数字,描述初始时的数列。
以下 M 行,每行一条命令,格式参见问题描述中的表格。
OUTPUT
对于输入数据中的 GET-SUM 和 MAX-SUM 操作,向输出文件依次打印结果,每个答案(数字)占一行。
SAMPLE
INPUT
9 8 2 -6 3 5 1 -5 -3 6 3 GET-SUM 5 4 MAX-SUM INSERT 8 3 -5 7 2 DELETE 12 1 MAKE-SAME 3 3 2 REVERSE 3 6 GET-SUM 5 4 MAX-SUMOUTPUT
-1
10
1
10
解题报告
做这道题前请做好心理准备= =
比如说你会看到这样的评论:
QhelDIV:记得byvoid的博客上说这个题他当时写了整整一天,
我大约写了8个小时?
这种长代码程序结构一定要简单简单再简单,否则就是无限的调试了
Chenyao2333:策爷:“splay/块状链表的自虐题。”。深刻理解到如果没有M倾向就不要去写这题了。。。
wumingshi:这道题太恶心辣
一定要处理好哨兵节点和null节点的数据,update时要注意!
【没有用哨兵节点的请随意
很裸的SpalySplay板子题,然而并不是那么好打= =
本来打了256行的数组板子
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 using namespace std; 5 inline int read(){ 6 int sum(0),f(1); 7 char ch(getchar()); 8 for(;ch<'0'||ch>'9';ch=getchar()) 9 if(ch=='-') 10 f=-1; 11 for(;ch>='0'&&ch<='9';sum=sum*10+(ch^48),ch=getchar()); 12 return sum*f; 13 } 14 int ch[4000001][2],f[4000001],key[4000001],size[4000001]; 15 int sum[4000001],maxl[4000001],maxr[4000001],maxn[4000001]; 16 int root,sz; 17 bool lazy[4000001],rev[4000001]; 18 inline void clear(int x){ 19 f[x]=ch[x][0]=ch[x][1]=size[x]=key[x]=sum[x]=0; 20 lazy[x]=rev[x]=maxl[x]=maxr[x]=0; 21 maxn[x]=-1000000000; 22 } 23 inline int get(int x){ 24 return ch[f[x]][1]==x; 25 } 26 inline int my_max(int a,int b){ 27 return a>b?a:b; 28 } 29 inline void swp(int &a,int &b){ 30 a^=b; 31 b^=a; 32 a^=b; 33 } 34 inline void update(int x){ 35 int l(ch[x][0]),r(ch[x][1]); 36 sum[x]=sum[l]+sum[r]+key[x]; 37 size[x]=size[l]+size[r]+1; 38 maxn[x]=maxl[r]+key[x]+maxr[l]; 39 if(l) 40 maxn[x]=my_max(maxn[x],maxn[l]); 41 if(r) 42 maxn[x]=my_max(maxn[x],maxn[r]); 43 maxl[x]=my_max(maxl[l],sum[l]+key[x]+maxl[r]); 44 maxr[x]=my_max(maxr[r],sum[r]+key[x]+maxr[l]); 45 } 46 inline void pushdown(int x){ 47 int l(ch[x][0]),r(ch[x][1]); 48 if(lazy[x]){ 49 rev[x]=lazy[x]=0; 50 if(l){ 51 lazy[l]=1; 52 key[l]=key[x]; 53 sum[l]=key[l]*size[l]; 54 } 55 if(r){ 56 lazy[r]=1; 57 key[r]=key[x]; 58 sum[r]=key[r]*size[r]; 59 } 60 if(key[x]>=0){ 61 if(l) 62 maxl[l]=maxr[l]=maxn[l]=sum[l]; 63 if(r) 64 maxl[r]=maxr[r]=maxn[r]=sum[r]; 65 } 66 else{ 67 if(l){ 68 maxl[l]=maxr[l]=0; 69 maxn[l]=key[l]; 70 } 71 if(r){ 72 maxl[r]=maxr[r]=0; 73 maxn[r]=key[r]; 74 } 75 } 76 } 77 if(rev[x]){ 78 rev[x]=0; 79 rev[l]^=1; 80 rev[r]^=1; 81 swp(maxl[l],maxr[l]); 82 swp(maxl[r],maxr[r]); 83 swp(ch[l][0],ch[l][1]); 84 swp(ch[r][0],ch[r][1]); 85 } 86 } 87 inline void rotate(int x){ 88 int p(f[x]),g(f[p]),which(get(x)); 89 pushdown(p); 90 pushdown(x); 91 ch[p][which]=ch[x][which^1]; 92 f[ch[p][which]]=p; 93 ch[x][which^1]=p; 94 f[p]=x; 95 f[x]=g; 96 if(g) 97 ch[g][ch[g][1]==p]=x; 98 update(p); 99 update(x); 100 } 101 inline void splay(int x,int y){ 102 pushdown(x); 103 for(int fa=f[x];fa!=y;rotate(x),fa=f[x]) 104 if(f[fa]!=y) 105 rotate(get(fa)==get(x)?fa:x); 106 if(!y) 107 root=x; 108 } 109 inline int find(int x){ 110 int now(root); 111 while(1){ 112 pushdown(now); 113 if(x<=size[ch[now][0]]) 114 now=ch[now][0]; 115 else{ 116 int tmp(size[ch[now][0]]+1); 117 if(x<=tmp) 118 return now; 119 x-=tmp; 120 now=ch[now][1]; 121 } 122 } 123 } 124 inline void build(int l,int r,int fa){ 125 if(l>r) 126 return ; 127 if(l==r){ 128 f[l]=fa; 129 size[l]=1; 130 sum[l]=key[l]; 131 if(key[l]>=0) 132 maxl[l]=maxr[l]=maxn[l]=key[l]; 133 else{ 134 maxl[l]=maxr[l]=0; 135 maxn[l]=key[l]; 136 } 137 if(fa){ 138 if(l<fa) 139 ch[fa][0]=l; 140 else 141 ch[fa][1]=l; 142 } 143 return; 144 } 145 int mid((l+r)>>1); 146 build(l,mid-1,mid); 147 build(mid+1,r,mid); 148 f[mid]=fa; 149 update(mid); 150 if(fa){ 151 if(mid<fa) 152 ch[fa][0]=mid; 153 else 154 ch[fa][1]=mid; 155 } 156 } 157 inline void erase(int x){ 158 if(!x) 159 return; 160 erase(ch[x][0]); 161 erase(ch[x][1]); 162 clear(x); 163 } 164 char op[10]; 165 inline int gg(){ 166 freopen("seq2005.in","r",stdin); 167 freopen("seq2005.out","w",stdout); 168 int n(read()),m(read()); 169 key[++sz]=-1000000000; 170 for(int i=1;i<=n;i++) 171 key[++sz]=read(); 172 key[++sz]=-1000000000; 173 build(1,n+2,0); 174 root=(n+3)>>1; 175 int all(n+2); 176 while(m--){//cout<<'*'<<m<<endl; 177 scanf("%s",op); 178 if(op[0]=='I'){ 179 int pos(read()+1),tot(read()),old(sz+1); 180 int x(find(pos)),y(find(pos+1)); 181 splay(x,0); 182 splay(y,x); 183 for(int i=1;i<=tot;i++) 184 key[++sz]=read(); 185 build(old,sz,0); 186 int rt((old+sz)>>1); 187 f[rt]=y; 188 ch[y][0]=rt; 189 update(y); 190 update(x); 191 all+=tot; 192 continue; 193 } 194 if(op[0]=='D'){ 195 int pos(read()),tot(read()); 196 int x(find(pos)),y(find(pos+tot+1)); 197 splay(x,0); 198 splay(y,x); 199 erase(ch[y][0]); 200 update(y); 201 update(x); 202 all-=tot; 203 continue; 204 } 205 if(op[0]=='R'){ 206 int pos(read()),tot(read()); 207 int x(find(pos)),y(find(pos+tot+1)); 208 splay(x,0); 209 splay(y,x); 210 int z(ch[y][0]); 211 if(!lazy[z]){ 212 rev[z]^=1; 213 swp(ch[z][0],ch[z][1]); 214 swp(maxl[z],maxr[z]); 215 update(y); 216 update(x); 217 } 218 continue; 219 } 220 if(op[0]=='G'){ 221 int pos(read()),tot(read()); 222 int x(find(pos)),y(find(pos+tot+1)); 223 splay(x,0); 224 splay(y,x); 225 printf("%d\n",sum[ch[y][0]]); 226 continue; 227 } 228 if(op[2]=='K'){ 229 int pos(read()),tot(read()),c(read()); 230 int x(find(pos)),y(find(pos+tot+1)); 231 splay(x,0); 232 splay(y,x); 233 int z(ch[y][0]); 234 lazy[z]=1; 235 key[z]=c; 236 sum[z]=size[z]*c; 237 if(c>=0) 238 maxl[z]=maxr[z]=maxn[z]=sum[z]; 239 else{ 240 maxl[z]=maxr[z]=0; 241 maxn[z]=c; 242 } 243 update(y); 244 update(x); 245 } 246 if(op[2]=='X'){ 247 int x(find(1)),y(find(all)); 248 splay(x,0); 249 splay(y,x); 250 printf("%d\n",maxn[ch[y][0]]); 251 } 252 } 253 return 0; 254 } 255 int K(gg()); 256 int main(){;}
然后成功在COGS上A了,然后我去了HZOJ、洛谷什么的。
MLE喵喵喵???我难道交了个MLE自动机喵喵喵???
//MLE自动机 int main(){ while(1) long long *x=new long long[500]; } //请不要作死在自己电脑上以及他人电脑上使用
最后我发现,COGS上的限制是这样的:
时间限制:3 s 内存限制:256 MB
然而其他OJ的限制是这样的:
时间限制: 1 Sec 内存限制: 64 MB
数组就莫名GG了= =
所以我学(xiu)习(gai)了某司机的指针板子,成功的get√到了新板子= =
264行SpalySplay板子奉上
1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 #include<vector> 6 using namespace std; 7 inline int read(){ 8 int sum(0),f(1); 9 char ch(getchar()); 10 for(;ch<'0'||ch>'9';ch=getchar()) 11 if(ch=='-') 12 f=-1; 13 for(;ch>='0'&&ch<='9';sum=sum*10+(ch^48),ch=getchar()); 14 return sum*f; 15 } 16 const int inf(0x2FFFFFFF); 17 inline int my_max(int a,int b){ 18 return a>b?a:b; 19 } 20 inline void swp(int &a,int &b){ 21 a^=b; 22 b^=a; 23 a^=b; 24 } 25 class SplayTree{ 26 private: 27 class Node{ 28 public: 29 int k,sz,sm,lm,rm,ms; 30 bool set,rev; 31 Node *fa,*ch[2]; 32 Node(const int& key){ 33 this->k=key; 34 this->sm=key; 35 this->ms=key; 36 this->lm=key>=0?key:0; 37 this->rm=key>=0?key:0; 38 this->sz=1; 39 this->fa=NULL; 40 this->ch[0]=NULL; 41 this->ch[1]=NULL; 42 this->rev=false; 43 this->set=false; 44 } 45 ~Node(){ 46 if(this->ch[0]!=NULL) 47 delete this->ch[0]; 48 if(this->ch[1]!=NULL) 49 delete this->ch[1]; 50 } 51 inline void pushup(){ 52 if(this!=NULL){ 53 this->sz=this->ch[0]->size()+this->ch[1]->size()+1; 54 this->sm=this->ch[0]->sum()+this->ch[1]->sum()+this->k; 55 this->lm=my_max(this->ch[0]->lmax(),this->ch[0]->sum()+this->k+this->ch[1]->lmax()); 56 this->rm=my_max(this->ch[1]->rmax(),this->ch[1]->sum()+this->k+this->ch[0]->rmax()); 57 this->ms=my_max(my_max(this->ch[0]->maxsum(),this->ch[1]->maxsum()),this->ch[0]->rmax()+this->k+this->ch[1]->lmax()); 58 } 59 } 60 inline void Swap(){ 61 if(this!=NULL){ 62 this->rev=!this->rev; 63 swp(this->lm,this->rm); 64 swap(this->ch[0],this->ch[1]); 65 } 66 } 67 inline void Set(const int &key){ 68 if(this!=NULL){ 69 this->set=true; 70 this->k=key; 71 this->sm=key*this->sz; 72 this->lm=my_max(this->sm,0); 73 this->rm=my_max(this->sm,0); 74 this->ms=my_max(this->sm,this->k); 75 } 76 } 77 inline void pushdown(){ 78 if(this->set){ 79 this->set=this->rev=false; 80 this->ch[0]->Set(this->k); 81 this->ch[1]->Set(this->k); 82 } 83 if(this->rev){ 84 this->rev=false; 85 this->ch[0]->Swap(); 86 this->ch[1]->Swap(); 87 } 88 } 89 inline int sum(){ 90 return this?this->sm:0; 91 } 92 inline int maxsum(){ 93 return this?this->ms:-inf; 94 } 95 inline int key(){ 96 return this?this->k:0; 97 } 98 inline int lmax(){ 99 return this?this->lm:0; 100 } 101 inline int rmax(){ 102 return this?this->rm:0; 103 } 104 inline int size(){ 105 return this?this->sz:0; 106 } 107 }*root; 108 inline void rotate(Node *root,int k){ 109 Node *tmp(root->ch[k^1]); 110 root->pushdown(); 111 tmp->pushdown(); 112 tmp->fa=root->fa; 113 if(root->fa==NULL) 114 this->root=tmp; 115 else 116 if(root->fa->ch[0]==root) 117 root->fa->ch[0]=tmp; 118 else 119 root->fa->ch[1]=tmp; 120 root->ch[k^1]=tmp->ch[k]; 121 if(tmp->ch[k]!=NULL) 122 tmp->ch[k]->fa=root; 123 tmp->ch[k]=root; 124 root->fa=tmp; 125 root->pushup(); 126 tmp->pushup(); 127 } 128 inline void Splay(Node *root,Node *fa=NULL){ 129 while(root->fa!=fa){ 130 int k(root->fa->ch[0]==root); 131 if(root->fa->fa==fa) 132 rotate(root->fa,k); 133 else{ 134 int d(root->fa->fa->ch[0]==root->fa); 135 rotate(k==d?root->fa->fa:root->fa,k); 136 rotate(root->fa,d); 137 } 138 } 139 } 140 inline Node* build(const vector<int> &v,int l,int r){ 141 if(l>r) 142 return NULL; 143 int mid((l+r)>>1); 144 Node *tmp(new Node(v[mid])); 145 tmp->ch[0]=build(v,l,mid-1); 146 tmp->ch[1]=build(v,mid+1,r); 147 if(tmp->ch[0]!=NULL) 148 tmp->ch[0]->fa=tmp; 149 if(tmp->ch[1]!=NULL) 150 tmp->ch[1]->fa=tmp; 151 tmp->pushup(); 152 return tmp; 153 } 154 public: 155 SplayTree():root(new Node(-inf)){ 156 this->root->ch[1]=new Node(-inf); 157 this->root->ch[1]->fa=this->root; 158 } 159 SplayTree(const vector<int> &v){ 160 this->root=build(v,0,v.size()-1); 161 } 162 ~SplayTree(){ 163 delete this->root; 164 } 165 Node* Kth(int pos){ 166 ++pos; 167 Node* root(this->root);//cout<<'+'; 168 while(root!=NULL){ 169 root->pushdown(); 170 int k(root->ch[0]->size()+1); 171 if(pos<k) 172 root=root->ch[0]; 173 else 174 if(pos==k) 175 return root; 176 else{ 177 pos-=k; 178 root=root->ch[1]; 179 } 180 } 181 return NULL; 182 } 183 inline int Sum(const int &pos,const int &len){ 184 this->Splay(this->Kth(pos-1)); 185 this->Splay(this->Kth(pos+len),this->root); 186 return this->root->ch[1]->ch[0]->sum(); 187 } 188 inline void Reverse(const int &pos,const int &len){ 189 this->Splay(this->Kth(pos-1)); 190 this->Splay(this->Kth(pos+len),this->root); 191 this->root->ch[1]->ch[0]->Swap(); 192 this->root->ch[1]->pushup(); 193 this->root->pushup(); 194 } 195 inline void Set(const int &pos,const int &len,const int &d){ 196 this->Splay(this->Kth(pos-1)); 197 this->Splay(this->Kth(pos+len),this->root); 198 this->root->ch[1]->ch[0]->Set(d); 199 this->root->ch[1]->pushup(); 200 this->root->pushup(); 201 } 202 inline void Insert(const int &pos,SplayTree *data){ 203 this->Splay(this->Kth(pos)); 204 this->Splay(this->Kth(pos+1),this->root); 205 Node *tmp(data->root); 206 data->root=NULL; 207 this->root->ch[1]->ch[0]=tmp; 208 tmp->fa=this->root->ch[1]; 209 this->root->ch[1]->pushup(); 210 this->root->pushup(); 211 } 212 inline void Delete(const int &pos,const int &len){ 213 this->Splay(this->Kth(pos-1)); 214 this->Splay(this->Kth(pos+len),this->root); 215 delete this->root->ch[1]->ch[0]; 216 this->root->ch[1]->ch[0]=NULL; 217 this->root->ch[1]->pushup(); 218 this->root->pushup(); 219 } 220 inline int maxsum(){ 221 return this->root->maxsum(); 222 } 223 }; 224 SplayTree *tree(new SplayTree()); 225 vector<int>v; 226 char op[20]; 227 int x,y; 228 inline int gg(){ 229 freopen("seq2005.in","r",stdin); 230 freopen("seq2005.out","w",stdout); 231 int n(read()),m(read()); 232 for(int i=0;i<n;i++) 233 v.push_back(read()); 234 tree->Insert(0,new SplayTree(v));//cout<<'*'; 235 while(m--){ 236 scanf("%s",op); 237 if(op[0]!='M'||op[2]!='X') 238 x=read(),y=read(); 239 if(op[0]=='G') 240 printf("%d\n",tree->Sum(x,y)); 241 else 242 if(op[0]=='D') 243 tree->Delete(x,y); 244 else 245 if(op[0]=='R') 246 tree->Reverse(x,y); 247 else 248 if(op[0]=='I'){ 249 v.clear(); 250 while(y--) 251 v.push_back(read()); 252 tree->Insert(x,new SplayTree(v)); 253 } 254 else 255 if(op[0]=='M'){ 256 if(op[2]=='K') 257 tree->Set(x,y,read()); 258 else 259 printf("%d\n",tree->maxsum()); 260 } 261 } 262 } 263 int K(gg()); 264 int main(){;}
这题,真的虐心啊= =