[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操作带来的影响

posted @ 2018-02-03 12:52  尹吴潇  阅读(157)  评论(0编辑  收藏  举报