• BZOJ 1500 NOI2005 维修数列 题解


    题目大意:要求维护一个序列,支持插入,删除,修改(将一段区间内的数全部设置为c),区间翻转,区间求和,区间最大和。

    splay维护。其中区间最大和用一个mmax值来记录,需要用lmax和rmax来辅助(代表前缀最大和和后缀最大和)。

    mmax有三种情况:区间全部在左子树中,区间全部在右子树中,区间跨越左右子树。

    lmax有两种情况:区间全部在左子树中,区间跨越左右子树。这样更新一下即可。

    (更新的时候有一些小细节,详见代码)

    注意Reverse操作。mmax不变,lmax和rmax交换。注意这题因为有附加值,不能像SuperMemo那题一样翻转时只修改标记,下传的时候再真正修改。

    注意操作结束之后要对父亲进行maintain维护。(不过在MakeSame和Reverse操作之后不maintain也可以,不知道为什么)

    (不过maintain操作是O(1)的,多maintain几次没坏处...)

      1 #include<cstdio>
      2 #include<algorithm>
      3 const int MAXN=1000000+10;
      4 const int INF=~0U>>1;
      5 int a[MAXN];
      6 struct Node{
      7     int s,v;
      8     int lmax,rmax,mmax,sum;
      9     bool rev,same;
     10     Node* p,*ch[2];
     11     Node() {same=sum=s=v=rev=0;lmax=rmax=mmax=-INF;}
     12     inline void maintain()
     13     {
     14         s=ch[0]->s+ch[1]->s+1;
     15         sum=v+ch[0]->sum+ch[1]->sum;
     16         lmax=std::max(ch[0]->lmax,ch[0]->sum+v+std::max(0,ch[1]->lmax));
     17         rmax=std::max(ch[1]->rmax,ch[1]->sum+v+std::max(0,ch[0]->rmax));
     18         mmax=std::max(std::max(ch[0]->mmax,ch[1]->mmax),std::max(0,ch[0]->rmax)+v+std::max(0,ch[1]->lmax));
     19     }
     20     inline void setc(Node* t,bool d)
     21     {
     22         ch[d]=t;
     23         t->p=this;
     24     }
     25     inline void MakeSame(int sv)
     26     {
     27         v=sv;
     28         same=1;
     29         sum=s*sv;
     30         mmax=rmax=lmax=std::max(v,sum);
     31     }
     32     inline void revIt()
     33     {
     34         std::swap(ch[0],ch[1]);
     35         std::swap(lmax,rmax);
     36         rev^=1;
     37     }
     38     inline bool d() {return p->ch[1]==this;}
     39     inline void pushdown();
     40 }Tnull,*null=&Tnull;
     41 inline void Node::pushdown()
     42 {
     43     if(rev)
     44     {
     45         if(ch[0]!=null) ch[0]->revIt();
     46         if(ch[1]!=null) ch[1]->revIt();
     47         rev=0;
     48     }
     49     if(same)
     50     {
     51         if(ch[0]!=null) ch[0]->MakeSame(v);
     52         if(ch[1]!=null) ch[1]->MakeSame(v);
     53         same=0;
     54     }
     55 }
     56 Node* root;
     57 inline void rot(Node* t)
     58 {
     59     Node* p=t->p;
     60     p->pushdown();t->pushdown();
     61     bool d=t->d();
     62     p->p->setc(t,p->d());
     63     p->setc(t->ch[d^1],d);
     64     t->setc(p,d^1);
     65     p->maintain();
     66     if(p==root)
     67         root=t;
     68 }
     69 void splay(Node* t,Node* f=null)
     70 {
     71     while(t->p!=f)
     72     {
     73         if(t->p->p==f) rot(t);
     74         else t->d()==t->p->d()?(rot(t->p),rot(t)):(rot(t),rot(t));
     75     }
     76     t->maintain();
     77 }
     78 Node* select(int k)
     79 {
     80     for(Node* t=root;;)
     81     {
     82         t->pushdown();
     83         int s=t->ch[0]->s;
     84         if(k==s) return t;
     85         if(k>s) k-=s+1,t=t->ch[1];
     86         else t=t->ch[0];
     87     }
     88 }
     89 inline Node*& get(int l,int r) //[l,r)
     90 {
     91     Node* L=select(l-1);
     92     Node* R=select(r);
     93     splay(L);
     94     splay(R,L);
     95     return R->ch[0];
     96 }
     97 void DeleteTree(Node*& t)
     98 {
     99     if(t==null) return;
    100     DeleteTree(t->ch[0]);
    101     DeleteTree(t->ch[1]);
    102     delete t;
    103     t=null;
    104 }
    105 Node* build(int l,int r) //[l,r)
    106 {
    107     if(l>=r) return null;
    108     int m=l+r>>1;
    109     Node* t=new Node();
    110     Node* L=build(l,m),*R=build(m+1,r);
    111     t->v=t->sum=t->lmax=t->rmax=t->mmax=a[m];
    112     t->setc(L,0);
    113     t->setc(R,1);
    114     t->maintain();
    115     return t;
    116 }
    117 void Insert(int pos,int tot)
    118 {
    119     if(!tot) return;
    120     for(int i=0;i<tot;++i) scanf("%d",a+i);
    121     Node* t=build(0,tot);
    122     splay(select(pos));
    123     splay(select(pos+1),root);
    124     root->ch[1]->setc(t,0);
    125     root->ch[1]->maintain();
    126     root->maintain();
    127 }
    128 inline void Delete(int pos,int tot)
    129 {
    130     if(!tot) return;
    131     Node*& t=get(pos,pos+tot);
    132     DeleteTree(t);
    133     root->ch[1]->maintain();
    134     root->maintain();
    135 }
    136 inline void MakeSame(int pos,int tot,int c)
    137 {
    138     if(!tot) return;
    139     Node*& t=get(pos,pos+tot);
    140     t->MakeSame(c); 
    141     t->p->maintain();
    142     t->p->p->maintain();
    143 }
    144 inline void Reverse(int pos,int tot)
    145 {
    146     if(!tot || tot==1) return;
    147     Node*& t=get(pos,pos+tot);
    148     t->revIt();
    149     t->p->maintain();
    150     t->p->p->maintain();
    151 }
    152 inline int GetSum(int pos,int tot)
    153 {
    154     if(!tot) return 0;
    155     Node*& t=get(pos,pos+tot);
    156     return t->sum;
    157 }
    158 inline int MaxSum()
    159 {
    160     Node*& t=get(1,root->s-1);
    161     return t->mmax;
    162 }
    163 int n,m;
    164 char s[20];
    165 int main()
    166 {
    167     //freopen("sequence.in","r",stdin);
    168     //freopen("sequence.out","w",stdout);
    169     scanf("%d%d",&n,&m);
    170     for(int i=1;i<=n;++i) scanf("%d",a+i);
    171     root=build(0,n+2);
    172     root->p=null;
    173     while(m--)
    174     {
    175         int pos,tot,c;
    176         scanf("%s",s);
    177         if(s[2]!='X') scanf("%d%d",&pos,&tot);
    178         if(s[2]=='K') scanf("%d",&c);
    179         switch(s[2])
    180         {
    181             case 'T':printf("%d\n",GetSum(pos,tot));
    182                      break;
    183             case 'S':Insert(pos,tot);
    184                      break;
    185             case 'V':Reverse(pos,tot);
    186                      break;
    187             case 'L':Delete(pos,tot);
    188                      break;
    189             case 'X':printf("%d\n",MaxSum());
    190                      break;
    191             case 'K':MakeSame(pos,tot,c);
    192                      break;
    193         }
    194     }
    195     return 0;
    196 }
    View Code
  • 相关阅读:
    SSIS Error:Package Validation Error. SSIS Error Code DTS_E_OLEDBERROR. .Error code: 0x80040E37. An OLE DB record is available. Hresult: 0x80040E37
    MDS
    oracle11g rac静默安装+racADG部署搭建
    oracle 19c 单机ADG部署
    对索引组织表以及簇表的一些理解
    对表的连接的总结
    全局临时表
    对分区表的一些总结
    对临时表空间的一些常用查询
    linux 常用命令总结
  • 原文地址:https://www.cnblogs.com/lowsfish/p/4342473.html
Copyright © 2020-2023  润新知