zoukankan      html  css  js  c++  java
  • [bzoj1500][NOI2005 维修数列] (splay区间操作)

    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

    Solution

    #include<cstdio>
    #include<iostream>
    #define N 500010
    #define inf 0x3f3f3f3f
    #define mid ((x>>1)+(y>>1)+(x&y&1))
    using namespace std;
    inline int Rin(){
      int x=0,c=getchar(),f=1;
      for(;c<48||c>57;c=getchar())
        if(!(c^45))f=-1;
      for(;c>47&&c<58;c=getchar())
        x=(x<<1)+(x<<3)+c-48;
      return x*f;
    }
    struct nt{
      nt*ch[2],*p;
      bool rev;int cov;
      int size,sum,v,lmx,rmx,mmx;
      bool d(){return this==p->ch[1];}
      void setc(nt*c,int d){
        ch[d]=c;
        c->p=this;
      }
      void revIt(){
        rev^=1;
        swap(lmx,rmx);
        swap(ch[0],ch[1]);
      }
      void covIt(int co){
        cov=v=co;
        sum=co*size;
        co>0?lmx=rmx=mmx=sum:
        lmx=rmx=mmx=co;
      }
      void pu(){
        size=1+ch[0]->size+ch[1]->size;
        sum=v+ch[0]->sum+ch[1]->sum;
        lmx=max(ch[0]->lmx,ch[0]->sum+v+max(ch[1]->lmx,0));
        rmx=max(ch[1]->rmx,ch[1]->sum+v+max(ch[0]->rmx,0));
        mmx=max(max(ch[0]->mmx,ch[1]->mmx),max(ch[0]->rmx,0)+v+max(ch[1]->lmx,0));
      }
      void relax(){
        if(rev)
          ch[0]->revIt(),
        ch[1]->revIt();
        if(cov^inf)
          ch[0]->covIt(cov),
        ch[1]->covIt(cov);
        rev=0;
        cov=inf;
      }
    };
    nt*null=new nt();
    nt*root=null;
    int n,a[N],m;
    char sign[10];
    nt*newnode(nt*p,int v){
      nt*o=new nt();
      o->size=1;
      o->v=o->sum=o->lmx=o->rmx=o->mmx=v;
      o->ch[0]=o->ch[1]=null;
      o->cov=inf;
      o->p=p;
      return o;
    }
    void rot(nt*&o){
      nt*p=o->p;
      p->relax();
      o->relax();
      bool d=o->d();
      p->p->setc(o,p->d());
      p->setc(o->ch[!d],d);
      o->setc(p,!d);
      p->pu();o->pu();
      if(p==root)root=o;
    }
    void splay(nt*o,nt*p){
      while(o->p!=p)
        if(o->p->p==p)
          rot(o);
        else
          o->d()^o->p->d()?(rot(o),rot(o)):(rot(o->p),rot(o));
      o->pu();
    }
    nt*build(int x,int y){
      if(x>y)return null;
      nt*o=newnode(o,a[mid]);
      o->setc(build(x,mid-1),0);
      o->setc(build(mid+1,y),1);
      o->pu();
      return o;
    }
    void del(nt*&o){
      if(o->ch[0]!=null)del(o->ch[0]);
      if(o->ch[1]!=null)del(o->ch[1]);
      delete o;
    }
    nt*kth(int k){
      for(nt*o=root;;){
        o->relax();
        if(k<=o->ch[0]->size)
          o=o->ch[0];
        else{
          k-=o->ch[0]->size+1;
          if(!k)return o;
          o=o->ch[1];
        }
      }
    }
    int main(){
      n=Rin(),m=Rin();
      for(int i=1;i<=n;i++)a[i]=Rin();
      root=build(0,n+1);
      root->p=null;
      int x,y,z;
      while(m--){
        scanf("%s",sign);
        switch(sign[2]){
        case'S':
          x=Rin(),y=Rin();
          for(int i=1;i<=y;i++)a[i]=Rin();
          splay(kth(x+1),null);
          splay(kth(x+2),root);
          root->ch[1]->setc(build(1,y),0);
          root->ch[1]->pu();
          root->pu();
          break;
        case'L':
          x=Rin(),y=Rin();
          splay(kth(x),null);
          splay(kth(x+y+1),root);
          del(root->ch[1]->ch[0]);
          root->ch[1]->ch[0]=null;
          root->ch[1]->pu();
          root->pu();
          break;
        case'K':
          x=Rin(),y=Rin(),z=Rin();
          splay(kth(x),null);
          splay(kth(x+y+1),root);
          root->ch[1]->ch[0]->covIt(z);
          root->ch[1]->pu();
          root->pu();
          break;
        case'T':
          x=Rin(),y=Rin();
          splay(kth(x),null);
          splay(kth(x+y+1),root);
          printf("%d
    ",root->ch[1]->ch[0]->sum);
          break;
        case'V':
          x=Rin(),y=Rin();
          splay(kth(x),null);
          splay(kth(x+y+1),root);
          root->ch[1]->ch[0]->revIt();
          root->ch[1]->pu();
          root->pu();
          break;
        case'X':
          splay(kth(1),null);
          splay(kth(root->size),root);
          printf("%d
    ",root->ch[1]->ch[0]->mmx);
          break;
        default:break;
        }
      }
      return 0;
    }
  • 相关阅读:
    课堂检测求一个数的各个位
    猜数字
    登录界面
    课后作业01
    java语言基础问题
    大道至简第一张用java撰写伪代码
    阅读“大道至简”的读后感
    iOS 瀑布流的基本原理
    iOS 生成二维码
    CNContact对通讯录的基本使用(第二篇)
  • 原文地址:https://www.cnblogs.com/keshuqi/p/6261436.html
Copyright © 2011-2022 走看看