[BZOJ 1500]维修数列 [Splay Tree从进阶到住院]

历尽艰辛终于A掉了这题QwQ

贴COGS评论区几句话=.=

策爷:“splay/块状链表的自虐题。”。深刻理解到如果没有M倾向就不要去写这题了。。

  -Chenyao2333

记得byvoid的博客上说这个题他当时写了整整一天,
我大约写了8个小时?
这种长代码程序结构一定要简单简单再简单,否则就是无限的调试了

  -QhelDIV

这道题太恶心辣
一定要处理好哨兵节点和null节点的数据,update时要注意!
【没有用哨兵节点的请随意

   -wumingshi

这题确实恶心还特喵的是个板子...

用Splay写的话思路非常明确,但是必须处理好两边的虚拟结点和空结点的标记值...(猝不及防的细节题...?)

算了算了先贴题面

1500: [NOI2005]维修数列

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 14422  Solved: 4692

Description

Input

输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目。
第2行包含N个数字,描述初始时的数列。
以下M行,每行一条命令,格式参见问题描述中的表格。
任何时刻数列中最多含有500 000个数,数列中任何一个数字均在[-1 000, 1 000]内。
插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes。

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-SUM

Sample Output

-1
10
1
10

HINT

首先简单梳理一下,题目要求支持的操作有:$Reverse/Set/Sum/MaxSum/Delete/Insert$.

其中需要下传标记的是$Set$和$Reverse$,分别使用两个$bool$型标记即可.其中$Set$操作标记的处理优先于$Reverse$因为$Set$操作会将整个区间设置为同一个值,翻转不翻转都一样233

我们注意到有$MaxSum$操作,这时我们需要分析一下.我们可以使用三个变量来存储有关信息:$lmax$存储以该区间左端开始向右的最大和,$rmax$存储以该区间右端为结尾向左的最大和,$maxSum$存储该区间内的最大连续和的值.这样就可以将$maxSum$分为三种情况:左子树的$maxSum$;右子树的$maxSum$;左子树$rmax$,右子树$lmax$和该节点的键值之和.分别代表完全位于左区间/完全位于右区间/跨越中间的最大连续和(此部分的分治策略可参见算法导论第三版中文版的4.1节).$lmax$和$rmax$则分别对应两种情况,以$lmax$为例,对应左子树的$lmax$值与左子树的$sum$值,该结点的键值和右子树的$lmax$值之和的最大值.$rmax$同理.

对于空结点要注意maxSum为-INF,其他值为0.(这个-INF坑死人了QwQ总是WA那一个点...)

更新时对于$sum<0$的情况要更新$lmax$与$rmax$为0,$maxSum$为键值.

代码非常锻炼码力...还有调试能力w...

对于调试可以参考一下我在下面代码中的 class SplayTree 里写的$Print$函数,按前序遍历顺序打印整棵树并按深度缩进...调试的时候帮了我不少忙来着w

袋马时间~~

GitHub

  1 /**************************************
  2       Judge Result: Accepted
  3 
  4 **************************************/
  5 #include <cstdio>
  6 #include <vector>
  7 #include <cstring>
  8 #include <cstring>
  9 #include <iostream>
 10 #include <algorithm>
 11 
 12 #define lch chd[0]
 13 #define rch chd[1]
 14 #define kch chd[k]
 15 #define xch chd[k^1]
 16 
 17 const int INF=0x2FFFFFFF;
 18 
 19 class SplayTree{
 20 private:
 21     struct Node{
 22         int k;
 23         int sz;
 24         int sm;
 25         int lm;
 26         int rm;
 27         int ms;
 28         bool set;
 29         bool rev;
 30         Node* prt;
 31         Node* chd[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->prt=NULL;
 40             this->lch=NULL;
 41             this->rch=NULL;
 42             this->rev=false;
 43             this->set=false;
 44         }
 45         ~Node(){
 46             if(this->lch!=NULL)
 47                 delete this->lch;
 48             if(this->rch!=NULL)
 49                 delete this->rch;
 50         }
 51         inline void Maintain(){
 52             if(this!=NULL){
 53                 this->sz=this->lch->size()+this->rch->size()+1;
 54                 this->sm=this->lch->sum()+this->rch->sum()+this->k;
 55                 this->lm=std::max(this->lch->lmax(),this->lch->sum()+this->k+this->rch->lmax());
 56                 this->rm=std::max(this->rch->rmax(),this->rch->sum()+this->k+this->lch->rmax());
 57                 this->ms=std::max(std::max(this->lch->maxSum(),this->rch->maxSum()),this->lch->rmax()+this->k+this->rch->lmax());
 58             }
 59         }
 60         inline void Swap(){
 61             if(this!=NULL){
 62                 this->rev=!this->rev;
 63                 std::swap(this->lm,this->rm);
 64                 std::swap(this->lch,this->rch);
 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=std::max(this->sm,0);
 73                 this->rm=std::max(this->sm,0);
 74                 this->ms=std::max(this->sm,this->k);
 75             }
 76         }
 77         inline void PushDown(){
 78             if(this->set){
 79                 this->set=this->rev=false;
 80                 this->lch->Set(this->k);
 81                 this->rch->Set(this->k);
 82             }
 83             if(this->rev){
 84                 this->rev=false;
 85                 this->lch->Swap();
 86                 this->rch->Swap();
 87             }
 88         }
 89         inline int sum(){
 90             return this==NULL?0:this->sm;
 91         }
 92         inline int maxSum(){
 93             return this==NULL?-INF:this->ms;
 94         }
 95         inline int key(){
 96             return this==NULL?0:this->k;
 97         }
 98         inline int lmax(){
 99             return this==NULL?0:this->lm;
100         }
101         inline int rmax(){
102             return this==NULL?0:this->rm;
103         }
104         inline int size(){
105             return this==NULL?0:this->sz;
106         }
107     }*root;
108     inline void Rotate(Node* root,int k){
109         Node* tmp=root->xch;
110         root->PushDown();
111         tmp->PushDown();
112         tmp->prt=root->prt;
113         if(root->prt==NULL)
114             this->root=tmp;
115         else if(root->prt->lch==root)
116             root->prt->lch=tmp;
117         else
118             root->prt->rch=tmp;
119         root->xch=tmp->kch;
120         if(tmp->kch!=NULL)
121             tmp->kch->prt=root;
122         tmp->kch=root;
123         root->prt=tmp;
124         root->Maintain();
125         tmp->Maintain();
126     }
127     void Splay(Node* root,Node* prt=NULL){
128         while(root->prt!=prt){
129             int k=root->prt->lch==root;
130             if(root->prt->prt==prt){
131                 Rotate(root->prt,k);
132             }
133             else{
134                 int d=root->prt->prt->lch==root->prt;
135                 Rotate(k==d?root->prt->prt:root->prt,k);
136                 Rotate(root->prt,d);
137             }
138         }
139     }
140     Node* Build(const std::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->lch=Build(v,l,mid-1);
146         tmp->rch=Build(v,mid+1,r);
147         if(tmp->lch!=NULL)
148             tmp->lch->prt=tmp;
149         if(tmp->rch!=NULL)
150             tmp->rch->prt=tmp;
151         tmp->Maintain();
152         return tmp;
153     }
154     void PrintTree(Node* root,int deep){
155         for(int i=0;i<deep;i++)
156             fputc(' ',stderr);
157         fprintf(stderr, "(root=0x%X,key=%d,sum=%d,size=%d,lmax=%d,rmax=%d,maxSum=%d)\n", root,root->key(),root->sum(),root->size(),root->lmax(),root->rmax(),root->maxSum());
158         if(root==NULL)
159             return;
160         PrintTree(root->lch,deep+1);
161         PrintTree(root->rch,deep+1);
162     }
163 public:
164     SplayTree(){
165         this->root=new Node(-INF);
166         this->root->rch=new Node(-INF);
167         this->root->rch->prt=this->root;
168     }
169     SplayTree(const std::vector<int>& v){
170         this->root=Build(v,0,v.size()-1);
171     }
172     ~SplayTree(){
173         delete this->root;
174     }
175     Node* Kth(int pos){
176         ++pos;
177         Node* root=this->root;
178         while(root!=NULL){
179             root->PushDown();
180             int k=root->lch->size()+1;
181             if(pos<k)
182                 root=root->lch;
183             else if(pos==k)
184                 return root;
185             else{
186                 pos-=k;
187                 root=root->rch;
188             }
189         }
190         return NULL;
191     }
192     inline int Sum(const int& pos,const int& len){
193         this->Splay(this->Kth(pos-1));
194         this->Splay(this->Kth(pos+len),this->root);
195         return this->root->rch->lch->sum();
196     }
197     inline void Reverse(const int& pos,const int& len){
198         this->Splay(this->Kth(pos-1));
199         this->Splay(this->Kth(pos+len),this->root);
200         this->root->rch->lch->Swap();
201         this->root->rch->Maintain();
202         this->root->Maintain();
203     }
204     inline void Set(const int& pos,const int& len,const int& d){
205         this->Splay(this->Kth(pos-1));
206         this->Splay(this->Kth(pos+len),this->root);
207         this->root->rch->lch->Set(d);
208         this->root->rch->Maintain();
209         this->root->Maintain();
210     }
211     inline void Insert(const int& pos,SplayTree* data){
212         this->Splay(this->Kth(pos));
213         this->Splay(this->Kth(pos+1),this->root);
214         Node* tmp=data->root;
215         data->root=NULL;
216         this->root->rch->lch=tmp;
217         tmp->prt=this->root->rch;
218         this->root->rch->Maintain();
219         this->root->Maintain();
220     }
221     inline void Delete(const int& pos,const int& len){
222         this->Splay(this->Kth(pos-1));
223         this->Splay(this->Kth(pos+len),this->root);
224         delete this->root->rch->lch;
225         this->root->rch->lch=NULL;
226         this->root->rch->Maintain();
227         this->root->Maintain();
228     }
229     inline int MaxSum(){
230         return this->root->maxSum();
231     }
232     void Print(){
233         this->PrintTree(this->root,0);
234     }
235 };
236 
237 int FastRead();
238 
239 int main(){
240     SplayTree* tree=new SplayTree();
241     std::vector<int> v;
242     int n=FastRead();
243     int m=FastRead();
244     int a,b;
245     char buf[20];
246     for(int i=0;i<n;i++){
247         v.push_back(FastRead());
248     }
249     tree->Insert(0,new SplayTree(v));
250     for(int i=0;i<m;i++){
251         scanf("%s",buf);
252         if(*buf!='M'||buf[2]!='X'){
253             a=FastRead();
254             b=FastRead();
255         }
256         if(*buf=='G'){
257             printf("%d\n",tree->Sum(a,b));
258         }
259         else if(*buf=='D')
260             tree->Delete(a,b);
261         else if(*buf=='R')
262             tree->Reverse(a,b);
263         else if(*buf=='I'){
264             v.clear();
265             while(b--)
266                 v.push_back(FastRead());
267             tree->Insert(a,new SplayTree(v));
268         }
269         else if(*buf=='M'){
270             if(buf[2]=='K')
271                 tree->Set(a,b,FastRead());
272             else
273                 printf("%d\n",tree->MaxSum());
274         }
275         // tree->Print();
276     }
277     return 0;
278 }
279 
280 int FastRead(){
281     int ans=0;
282     bool neg=false;
283     register char ch=getchar();
284     while(!isdigit(ch)){
285         if(ch=='-')
286             neg=true;
287         ch=getchar();
288     }
289     while(isdigit(ch)){
290         ans=ans*10+ch-'0';
291         ch=getchar();
292     }
293     if(neg)
294         ans=-ans;
295     return ans;
296 }
Backup

然后该放图了来着w

 

posted @ 2017-07-24 11:43  rvalue  阅读(358)  评论(0编辑  收藏  举报