• bzoj1500 [NOI2005]维修数列


    坑点:GET-SUM的第二个参数可以是0,这时直接输出0.(论1A和差点1A的区别)(没事反正这次是在cogs上交的我下次重写一遍bzoj上一定能1A)(UPD:然而在bz上也没有1A,释放子树的函数没有调用,MLE了。。。顺便在cogs上A的代码是错的,因为cogs内存算的不转所以该MLE没有MLE)

    最大子段和的处理需要对每棵子树维护一下最大前缀和,最大后缀和以及最大子段和(都不能为空)。把这些数据打包写成一个结构体就比较整洁了。

    每个子树的数据=左子树+根节点+右子树,数据打包之后这两个‘+’本质是相同的操作。

    然后就都是套路了,split一下,merge一下。。。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    struct data{
      int lmax,rmax,mmax,sum;
      void rev(){
        swap(lmax,rmax);
      }
      data(){}
      data(int x){lmax=rmax=sum=mmax=x;}
      data(int x,int num){
        sum=x*num;
        lmax=rmax=mmax=max(x,sum);
      }
      data operator +(const data &B)const{
        data C;
        C.sum=sum+B.sum;
        C.lmax=max(lmax,sum+B.lmax);C.rmax=max(B.rmax,B.sum+rmax);
        C.mmax=max(max(mmax,B.mmax),rmax+B.lmax);
        return C;
      }
    };
    const int maxn=500005;
    struct node{
      int mk,mkt;//mkt==2:change mkt==1:reverse mkt==0:nothing
      data subtree,rtnode;
      node* ch[2],*prt;
      int sz;
      node(){}
      node(int x,node* p){
        ch[0]=ch[1]=0;prt=p;mk=mkt=0;
        subtree=rtnode=data(x);
      }
      void setto(int x){
        mkt=2;mk=x;rtnode=data(x);subtree=data(x,sz);
      }
      void rev(){
        if(mkt==2)return;
        mkt^=1;subtree.rev();
      }
      void update(){
        subtree=rtnode;sz=1;
        if(ch[0])subtree=ch[0]->subtree+subtree,sz+=ch[0]->sz;
        if(ch[1])subtree=subtree+ch[1]->subtree,sz+=ch[1]->sz;
      }
      void pushdown(){
        if(mkt==1){
          swap(ch[0],ch[1]);
          if(ch[0])ch[0]->rev();if(ch[1])ch[1]->rev();
          mkt=0;
        }else if(mkt==2){
          if(ch[0])ch[0]->setto(mk);if(ch[1])ch[1]->setto(mk);
          mkt=0;
        }
      }
    };
    node *root,*c0,*c1;
    node *kth(node *rt,int k){
      rt->pushdown();
      int lsz=(rt->ch[0])?rt->ch[0]->sz:0;
      if(k<=lsz)return kth(rt->ch[0],k);
      if(k==lsz+1)return rt;
      return kth(rt->ch[1],k-lsz-1);
    }
    inline int isch1(node *rt){return rt==(rt->prt->ch[1]);}
    void rot(node *rt,int t){
      node *c=rt->ch[t],*p=rt->prt;
      rt->pushdown();c->pushdown();
      if(!p)root=c;
      else p->ch[isch1(rt)]=c;
      c->prt=p;
      rt->ch[t]=c->ch[t^1];
      if(c->ch[t^1])c->ch[t^1]->prt=rt;
      rt->prt=c;c->ch[t^1]=rt;
      rt->update();c->update();
    }
    void splay(node* rt,node *ed){
      node *p,*g;
      while((p=rt->prt)&&(g=p->prt)){
        g->pushdown();p->pushdown();
        if(p==ed)return;
        if(g==ed){rot(p,isch1(rt));return;}
        int t1=isch1(rt),t2=isch1(p);
        if(t1==t2){rot(g,t2);rot(p,t1);}
        else {rot(p,t1);rot(g,t2);}
      }
      if(ed==0&&p!=0){p->pushdown();rot(p,isch1(rt));}
    }
    void split(int l,int r){
      splay(kth(root,l),0);
      c0=root->ch[0];
      if(c0){c0->prt=0;root->ch[0]=0;root->update();}
      splay(kth(root,r-l+1),0);
      c1=root->ch[1];
      if(c1){c1->prt=0;root->ch[1]=0;root->update();}
    }
    void split(int l){
      if(l==0){
        c1=root;c0=0;root=0;return;
      }
      splay(kth(root,l),0);
      c1=root->ch[1];
      if(c1){c1->prt=0;root->ch[1]=0;root->update();}
      c0=root;root=0;
    }
    void merge3(){
      splay(kth(root,1),0);root->ch[0]=c0;
      if(c0){c0->prt=root;root->update();}
      splay(kth(root,root->sz),0);root->ch[1]=c1;
      if(c1){c1->prt=root;root->update();}
    }
    void merge2(){
      if(!c1)root=c0;
      else if(!c0)root=c1;
      else{
        root=c1;splay(kth(root,1),0);root->ch[0]=c0;c0->prt=root;root->update();
      }
    }
    void remove(int l,int r){
      split(l,r);merge2();//UPD:merge2()之前应有一句del(root),释放所有删除的节点 del的实现: void del(node* rt){if(!rt)return;del(rt->ch[0]);del(rt->ch[1]);delete rt;}
    }
    void reverse(int l,int r){
      split(l,r);root->rev();root->pushdown();merge3();
    }
    void change(int l,int r,int x){
      split(l,r);root->setto(x);root->pushdown();merge3();
    }
    void getsum(int l,int r){
      if(l>r){printf("0
    ");return;}
      split(l,r);printf("%d
    ",root->subtree.sum);merge3();
    }
    void maxsum(){printf("%d
    ",root->subtree.mmax);}
    int seq[maxn];
    void build(node* &rt,node *p,int l,int r){
      if(l>r)return;
      int mid=(l+r)>>1;
      rt=new node(seq[mid],p);
      build(rt->ch[0],rt,l,mid-1);build(rt->ch[1],rt,mid+1,r);
      rt->update();
    }
    void insert(int pos,int len){
      split(pos);build(root,0,1,len);merge3();
    }
    int main(){
    //  freopen("seq2005.in","r",stdin);
    //  freopen("seq2005.out","w",stdout);
      int n,m;scanf("%d%d",&n,&m);
      for(int i=1;i<=n;++i)scanf("%d",seq+i);
      build(root,0,1,n);
      char buf[20];
      int x,y,z;
      for(int i=1;i<=m;++i){
        scanf("%s",buf);
        if(buf[0]=='I'){
          scanf("%d%d",&x,&y);
          for(int i=1;i<=y;++i)scanf("%d",seq+i);
          insert(x,y);
        }else if(buf[0]=='D'){
          scanf("%d%d",&x,&y);remove(x,x+y-1);
        }else if(buf[0]=='G'){
          scanf("%d%d",&x,&y);getsum(x,x+y-1);
        }else if(buf[0]=='R'){
          scanf("%d%d",&x,&y);reverse(x,x+y-1);
        }else if(buf[2]=='X'){
          maxsum();
        }else {
          scanf("%d%d%d",&x,&y,&z);change(x,x+y-1,z);
        }
      }
    //  fclose(stdin);fclose(stdout);
      return 0;
    }
  • 相关阅读:
    Linux下的邮件发送
    Linux下用户和raid练习题
    Linux centos7.5操作系统的安装
    Linux chattr文件锁
    Linux系统下root密码丢失解决方案
    周总结2
    课堂作业1
    开课博客
    阅读3
    作业8
  • 原文地址:https://www.cnblogs.com/liu-runda/p/6339799.html
Copyright © 2020-2023  润新知