• [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)
    ", 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
    ",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
    ",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

  • 相关阅读:
    poj3411
    2241 排序二叉树
    1004 四子连棋
    Poj1482
    poj2046
    Poj3087
    poj3414
    php使用flock堵塞写入文件和非堵塞写入文件
    HTML样式以及使用
    高效程序猿的狂暴之路
  • 原文地址:https://www.cnblogs.com/rvalue/p/7228147.html
Copyright © 2020-2023  润新知