现在的位置: 首页 > 综合 > 正文

HYSBZ 1500 维修数列(Splay)

2014年08月29日 ⁄ 综合 ⁄ 共 4125字 ⁄ 字号 评论关闭

             非常恶心的一道题,本来的操作并不是十分难写,主要是求最大子段和翻转还有set的操作使得让懒惰标记十分容易写错。对于一个结点,我们要维护以下几个值:size[i]该区间结点个数,flip[i]该区间是否被翻转,setv[i]该区间是否被赋为一个值,sum[i]该区间的和,smax[i]区间最大子段和,pmax[i]区间最大前缀和,fmax[i]区间最大后缀和。合并的过程比较麻烦,需要考虑不少状况,详细情况看代码……还有不进行空间回收会发生TLE,另外,对于空结点的处理,smax[i],pmax[i]和fmax[i]都要赋值为-inf以确保不会被选中,若不这么写那么在合并结点的时候要加上判断。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<set>
#include<stack>
//#include<cmath>
#include<vector>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-9
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
const int maxn=500000+10;
int ch[maxn][2],val[maxn],pre[maxn],size[maxn],flip[maxn],setv[maxn];
int sum[maxn],smax[maxn],fmax[maxn],pmax[maxn],S[maxn],root,tot,tot2;
int num[maxn];
char str[20];
void NewNode(int &rt,int fa,int v)
{
    if(tot2)
        rt=S[tot2--];
    else
        rt=++tot;
    ch[rt][0]=ch[rt][1]=flip[rt]=setv[rt]=0;
    val[rt]=sum[rt]=smax[rt]=fmax[rt]=pmax[rt]=v;
    pre[rt]=fa;
}
void PushUp(int rt)
{
    int ls=ch[rt][0],rs=ch[rt][1];
    size[rt]=size[ls]+size[rs]+1;
    sum[rt]=sum[ls]+sum[rs]+val[rt];
    smax[rt]=max(smax[ls],smax[rs]);
    smax[rt]=max(smax[rt],val[rt]);
    smax[rt]=max(smax[rt],fmax[ls]+val[rt]);
    smax[rt]=max(smax[rt],pmax[rs]+val[rt]);
    smax[rt]=max(smax[rt],fmax[ls]+val[rt]+pmax[rs]);

    pmax[rt]=max(pmax[ls],sum[ls]+val[rt]);
    pmax[rt]=max(pmax[rt],sum[ls]+val[rt]+pmax[rs]);
    fmax[rt]=max(fmax[rs],sum[rs]+val[rt]);
    fmax[rt]=max(fmax[rt],sum[rs]+val[rt]+fmax[ls]);
}
void fson(int rt)
{
    if(!rt) return ;
    swap(ch[rt][0],ch[rt][1]);
    swap(fmax[rt],pmax[rt]);
    flip[rt]^=1;
}
void sson(int rt,int v)
{
    if(!rt) return ;
    val[rt]=v;
    sum[rt]=v*size[rt];
    pmax[rt]=smax[rt]=fmax[rt]=max(v,sum[rt]);
    setv[rt]=1;
}
void PushDown(int rt)
{
    if(flip[rt])
    {
        fson(ch[rt][0]);
        fson(ch[rt][1]);
        flip[rt]=0;
    }
    if(setv[rt])
    {
        sson(ch[rt][0],val[rt]);
        sson(ch[rt][1],val[rt]);
        setv[rt]=0;
    }
}
void Rotate(int x,int kind)
{
    int y=pre[x];
    PushDown(y);PushDown(x);
    ch[y][kind^1]=ch[x][kind];
    pre[ch[x][kind]]=y;
    if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x;
    pre[x]=pre[y];
    ch[x][kind]=y;
    pre[y]=x;
    PushUp(y);
}
void Splay(int rt,int goal)
{
    PushDown(rt);
    while(pre[rt]!=goal)
    {
        int y=pre[rt];
        if(pre[y]==goal)
            Rotate(rt,ch[y][0]==rt);
        else
        {
            int kind=ch[pre[y]][0]==y;
            if(ch[y][kind]==rt)
            {
                Rotate(rt,kind^1);
                Rotate(rt,kind);
            }
            else
            {
                Rotate(y,kind);
                Rotate(rt,kind);
            }
        }
    }
    PushUp(rt);
    if(goal==0) root=rt;
}
void RotateTo(int k,int goal)
{
    int rt=root;
    PushDown(rt);
    while(size[ch[rt][0]]!=k)
    {
        if(size[ch[rt][0]]>k)
            rt=ch[rt][0];
        else
        {
            k-=(size[ch[rt][0]]+1);
            rt=ch[rt][1];
        }
        PushDown(rt);
    }
    Splay(rt,goal);
}
void build(int l,int r,int &rt,int fa)
{
    if(l>r) return ;
    int m=(l+r)>>1;
    NewNode(rt,fa,num[m]);
    build(l,m-1,ch[rt][0],rt);
    build(m+1,r,ch[rt][1],rt);
    PushUp(rt);
}
void Insert(int k,int n)
{
    RotateTo(k,0);
    RotateTo(k+1,root);
    build(0,n-1,ch[ch[root][1]][0],ch[root][1]);
    PushUp(ch[root][1]);
    PushUp(root);
}
void erase(int rt)
{
    if(!rt) return ;
    S[++tot2]=rt;
    erase(ch[rt][0]);
    erase(ch[rt][1]);
}
void Delete(int k,int n)
{
    RotateTo(k-1,0);
    RotateTo(k+n,root);
    erase(ch[ch[root][1]][0]);
    ch[ch[root][1]][0]=0;
    PushUp(ch[root][1]);
    PushUp(root);
}
void Make_setv(int k,int n,int v)
{
    RotateTo(k-1,0);
    RotateTo(k+n,root);
    sson(ch[ch[root][1]][0],v);
    PushUp(ch[root][1]);
    PushUp(root);
}
void Flip(int k,int n)
{
    RotateTo(k-1,0);
    RotateTo(k+n,root);
    fson(ch[ch[root][1]][0]);
    PushUp(ch[root][1]);
    PushUp(root);
}
int getSum(int k,int n)
{
    RotateTo(k-1,0);
    RotateTo(k+n,root);
    return sum[ch[ch[root][1]][0]];
}
int getMaxsum(int k,int n)
{
    RotateTo(k-1,0);
    RotateTo(k+n,root);
    return smax[ch[ch[root][1]][0]];
}
void init(int n)
{
    for(int i=0;i<n;++i)
        scanf("%d",&num[i]);
    ch[0][0]=ch[0][1]=pre[0]=size[0]=flip[0]=setv[0]=0;
    smax[0]=pmax[0]=fmax[0]=-inf;
    sum[0]=val[0]=root=tot=tot2=0;
    NewNode(root,0,0);
    NewNode(ch[root][1],root,0);
    build(0,n-1,ch[ch[root][1]][0],ch[root][1]);
    PushUp(ch[root][1]);
    PushUp(root);
}
int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        init(n);
        while(m--)
        {
            scanf("%s",str);
            if(str[0]=='M'&&str[2]=='X')
                printf("%d\n",getMaxsum(1,size[root]-2));
            else
            {
                int k,len,v;
                scanf("%d%d",&k,&len);
                if(str[0]=='I')
                {
                    for(int i=0;i<len;++i)
                        scanf("%d",&num[i]);
                    Insert(k,len);
                }
                else if(str[0]=='D')
                    Delete(k,len);
                else if(str[0]=='M')
                {
                    scanf("%d",&v);
                    Make_setv(k,len,v);
                }
                else if(str[0]=='R')
                    Flip(k,len);
                else
                    printf("%d\n",getSum(k,len));
            }
        }
    }
    return 0;
}




抱歉!评论已关闭.