• [NOI2005]维护数列


    链接:https://www.luogu.org/problemnew/show/P2042

    题解:

    写模板这道题的时候遇到一些错误

    1.对于元素初始化,又没写全面

    2.max_pre 没有更新当前点

    3.search里面少down了

    注意点非常多的一道题

    首先维护最大序列和可以类似线段树,维护max_all,max_pre,max_ess,

    这样三个简单的方程就可以转移了

    *但是 由于题目要求max_all中至少有一个元素,所以应该求一下其中的最大值

    另外对于insert操作只需加入用那些节点建一颗新树,再连上去就可以了

    *另外 这题的内存是会超的,所以要用内存池记录删去的元素

    其中内存池中的元素要注意将其之前的值清空

    其他就是平衡树的基本操作了

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    #define maxn 1111
    #define INF 20000
    int q1,q2,max_number[maxn],n,m,lazy[maxn],leftson[maxn],rightson[maxn],data[maxn],fa[maxn],root,
    num,max_all[maxn],max_pre[maxn],max_ess[maxn],count2[maxn],sum[maxn],a[maxn],b[maxn];
    queue<int> q;
    bool rev[maxn];
    void down(int x)
    {
        if (x==0) return;
        if (lazy[x]!=-INF)
        {
            max_number[x]=lazy[x]; rev[x]=0;
            data[x]=lazy[x];
            sum[x]=count2[x]*lazy[x];
            if (lazy[x]>=0)
            { 
                max_pre[x]=count2[x]*lazy[x];
                max_ess[x]=count2[x]*lazy[x];
                max_all[x]=count2[x]*lazy[x];
            } else
            {
                max_pre[x]=max_ess[x]=max_all[x]=0;
            }
            lazy[leftson[x]]=lazy[x];
            lazy[rightson[x]]=lazy[x];
            lazy[x]=-INF; 
        }
        if (rev[x])
        {
            swap(leftson[x],rightson[x]);
          swap(max_pre[x],max_ess[x]);
            rev[leftson[x]]^=1; rev[rightson[x]]^=1;
            rev[x]=0;
        }
    }
    void updata(int x)
    {
        down(leftson[x]); down(rightson[x]);
        max_number[x]=max(max(max_number[leftson[x]],max_number[rightson[x]]),data[x]);
        count2[x]=count2[leftson[x]]+count2[rightson[x]]+1;
        sum[x]=sum[leftson[x]]+sum[rightson[x]]+data[x];
        max_pre[x]=max(max_pre[leftson[x]],sum[leftson[x]]+data[x]+max_pre[rightson[x]]);
        max_ess[x]=max(max_ess[rightson[x]],sum[rightson[x]]+data[x]+max_ess[leftson[x]]);
        max_all[x]=max(max(max_all[leftson[x]],max_all[rightson[x]]),max_ess[leftson[x]]+data[x]+max_pre[rightson[x]]);
    }
    void rotate(int x,int y)
    {
        int father=fa[x];
        down(father); down(x);
        if (y==1)
        {
            rightson[father]=leftson[x]; 
            if (leftson[x]) fa[leftson[x]]=father;
        } else
        {
            leftson[father]=rightson[x];
            if (rightson[x]) fa[rightson[x]]=father;
        }
        fa[x]=fa[father];
        if (fa[father])
        {
            if (leftson[fa[father]]==father)
              leftson[fa[father]]=x;
            else rightson[fa[father]]=x; 
        }
        fa[father]=x;
        if (y==1) leftson[x]=father; else rightson[x]=father;
        updata(father); updata(x);
    }
    void splay(int x,int goal)
    {
        if (x==root) return;
        int father;
        while (fa[x]!=goal)
        {
            father=fa[x];
            if (fa[father]==goal)
            {
                if (x==leftson[father]) rotate(x,2);
                else rotate(x,1);
            } else
            {
                if (father==leftson[fa[father]])
                {
                    if (x==leftson[father])
                      rotate(father,2),rotate(x,2);
                    else rotate(x,1),rotate(x,2);
                } else
                {
                    if (x==rightson[father])
                      rotate(father,1),rotate(x,1);
                    else rotate(x,2),rotate(x,1);
                }
            }  
        }
        if (goal==0) root=x;
    }
    #define mid (h+t)/2
    void build(int h,int t,int father,bool x,int a[maxn])
    {
         num=q.front(); q.pop();
         count2[num]=1; data[num]=a[mid]; fa[num]=father;
         if (father)
         {
               if (x==1) leftson[father]=num; else rightson[father]=num;
         }
         int tmp=num;
         if (h<mid) build(h,mid-1,tmp,1,a);
         if (mid<t) build(mid+1,t,tmp,0,a);
         updata(tmp);
    }
    int search(int goal)
    {
        int x=root,cnt=1;
        while (x)
        {
            down(x);
            if (cnt+count2[leftson[x]]==goal) return(x);
            if (count2[leftson[x]]+cnt<goal)
            {
                cnt+=count2[leftson[x]]+1; x=rightson[x];
            } else
            {
                x=leftson[x];
            }
        }
    }
    void reserve(int x,int y)
    {
          
        int x1=search(x),y1=search(y+2);
        splay(x1,0);
        splay(y1,x1);
        rev[leftson[y1]]^=1;
    }
    void recycle(int x)
    {
        if (x==0) return;
        recycle(leftson[x]);
        recycle(rightson[x]);
        max_number[x]=-INF; lazy[x]=-INF; rev[x]=0;
        leftson[x]=0; rightson[x]=0; max_pre[x]=0;
        max_all[x]=0; max_ess[x]=0; sum[x]=0;
        q.push(x); q1++;
    }
    void del(int x,int y,int num)
    {
        int x1=search(x),y1=search(y+2);
        splay(x1,0);
        splay(y1,x1);
        recycle(leftson[y1]);
        leftson[y1]=0; 
        updata(y1); updata(x1);
    }
    void ins(int x,int y,int a[maxn],int l)
    {
        q2+=l;
        int x1=search(x),y1=search(y+2);
        splay(x1,0);
        splay(y1,x1);
        int tmp=q.front();
        build(1,l,0,0,a);
        fa[tmp]=y1; leftson[y1]=tmp;
        updata(y1); updata(x1);
    }
    void query1(int x,int y)
    {
        int x1=search(x),y1=search(y+2);
        splay(x1,0); splay(y1,x1);
        cout<<sum[leftson[y1]]<<endl;
    }
    void query2(int x,int y)
    {
        int x1=search(x),y1=search(y+2);
        splay(x1,0); splay(y1,x1);
      if (max_number[leftson[y1]]>0)
          cout<<max_all[leftson[y1]]<<endl;
        else cout<<max_number[leftson[y1]]<<endl;
    }
    void change(int x,int y,int z)
    {
        int x1=search(x),y1=search(y+2);
        splay(x1,0);splay(y1,x1);
        lazy[leftson[y1]]=z;
    }
    char c[100];
    int main()
    {
        freopen("noip.in","r",stdin);
        freopen("noip.out","w",stdout);
        std::ios::sync_with_stdio(false);
        cin>>n>>m;
        for (int i=1;i<=maxn-10;i++) q.push(i); 
        for (int i=0;i<=maxn-1;i++) lazy[i]=-INF,max_number[i]=-INF;
        for (int i=1;i<=n;i++) cin>>a[i]; a[0]=-INF; a[n+1]=-INF;
        build(0,n+1,0,0,a); root=1;
    //    for (int i=0;i<=n+1;i++) insert(i,a[i]);
      int ask=0;
        for (int i=1;i<=m;i++)
        {
            ask=max(ask,n);
            int d,e,f;
            cin>>c;
            if (c[2]=='S')
            {
                cin>>d>>e;
                for (int j=1;j<=e;j++) cin>>b[j];
                ins(d+1,d,b,e); n+=e; 
            }
            if (c[2]=='L')
            {
                cin>>d>>e;
                del(d,d+e-1,e); n-=e;
            }
            if (c[2]=='V')
            {
                cin>>d>>e;
                reserve(d,d+e-1);
            }
            if (c[2]=='K')
            {
                cin>>d>>e>>f;
                change(d,d+e-1,f);
            }
            if (c[2]=='T')
            {
                cin>>d>>e;
                query1(d,d+e-1);
            }
            if (c[2]=='X')
            {
                query2(1,n);
            }
        }
    //    cout<<ask<<" "<<q1<<" "<<q2;
    /*    cout<<endl<<endl<<endl<<endl;
        while (!q.empty())
        {
            cout<<q.front()<<endl;
            q.pop();
         } */
    }

     总结一下splay,打标记就是直接打得事情

    每份代码里的splay和rotate操作是一样的

    updata通过左右节点来计算当前节点

    down将标记下传m,注意要考虑一下rev操作带来的影响

  • 相关阅读:
    在IIS中浏览网站时出现:无法打开登录所请求的数据库 "***",登录失败
    Java中的深拷贝和浅拷贝(转载)
    Java的Final和C#的Const,Readonly比较分析(转载)
    C#中的Sealed和J#中的Final比较(转载)
    Java全系列帮助文档下载
    The Willpower Instinct(自控力,意志力)
    瓦片地图的前世今生(转载)
    创建CUDA项目
    CUDA warning C4819的消除
    并行调用
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/8409183.html
Copyright © 2020-2023  润新知