1500: [NOI2005]维修数列

题目链接

题目大意:维护一个数列,支持一堆操作(懒得写了)

题解:上fhq treap……

我的收获:2333

#include <cstdio>
#include <queue>
#include <cstdlib>
using namespace std;

#define N 500010
#define INF 0x3f3f3f3f

int n,m,root,cnt;
int ch[N][2],siz[N];
int k[N],tar[N],sum[N];
int lmx[N],rmx[N],tmx[N];
int cov[N];
bool rev[N];
int flag;

queue<int> trash;

inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

inline int max(int x,int y){return x>y?x:y;}
inline void swap(int &x,int &y){x^=y^=x^=y;}

/*
inline int newnode(int v)
{
    int x;
    if(!trash.empty()) x=trash.front(),trash.pop();
    else x=++cnt;
    cov[x]=INF,tar[x]=rand(),siz[x]=1;
    k[x]=sum[x]=tmx[x]=v;
    lmx[x]=rmx[x]=max(v,0);
    return x;
}
*/

int newnode(int v)
{
    int x;
    if (!trash.empty())
        x=trash.front(),trash.pop();
    else
        x=++cnt;
    ch[x][0]=ch[x][1]=rev[x]=0;
    cov[x]=INF,tar[x]=rand(),siz[x]=1;
    k[x]=sum[x]=tmx[x]=v;
    lmx[x]=rmx[x]=max(v,0);
    return x;
}

inline void rever(int x)
{
    swap(ch[x][0],ch[x][1]);
    swap(lmx[x],rmx[x]);
    rev[x]^=1;
}

inline void cover(int x,int v)
{
    k[x]=v,sum[x]=siz[x]*v;
    lmx[x]=rmx[x]=max(sum[x],0);
    tmx[x]=max(sum[x],k[x]);
    cov[x]=v;
}

/*
inline void update(int x)
{
    int l=ch[x][0],r=ch[x][1];
    siz[x]=siz[l]+siz[r]+1;
    sum[x]=sum[l]+sum[r]+k[x];
    tmx[x]=max(tmx[l],tmx[r]);
    tmx[x]=max(tmx[x],rmx[l]+k[x]+lmx[r]);
    lmx[x]=max(lmx[l],lmx[r]+k[x]+sum[l]);
    rmx[x]=max(rmx[r],rmx[l]+k[x]+sum[r]);
}
*/

void update(int x)
{
    if (ch[x][0] && ch[x][1])
    {
        siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
        sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+k[x];
        tmx[x]=max(tmx[ch[x][0]],tmx[ch[x][1]]);
        tmx[x]=max(tmx[x],rmx[ch[x][0]]+k[x]+lmx[ch[x][1]]);
        lmx[x]=max(lmx[ch[x][0]],sum[ch[x][0]]+k[x]+lmx[ch[x][1]]);
        rmx[x]=max(rmx[ch[x][1]],sum[ch[x][1]]+k[x]+rmx[ch[x][0]]);
    }
    else
    if (ch[x][0])
    {
        siz[x]=siz[ch[x][0]]+1;
        sum[x]=sum[ch[x][0]]+k[x];
        tmx[x]=max(tmx[ch[x][0]],rmx[ch[x][0]]+k[x]);
        lmx[x]=max(lmx[ch[x][0]],sum[ch[x][0]]+k[x]);
        lmx[x]=max(0,lmx[x]);
        rmx[x]=max(0,k[x]+rmx[ch[x][0]]);
    }
    else
    if (ch[x][1])
    {
        siz[x]=siz[ch[x][1]]+1;
        sum[x]=sum[ch[x][1]]+k[x];
        tmx[x]=max(tmx[ch[x][1]],lmx[ch[x][1]]+k[x]);
        rmx[x]=max(rmx[ch[x][1]],sum[ch[x][1]]+k[x]);
        rmx[x]=max(0,rmx[x]);
        lmx[x]=max(0,lmx[ch[x][1]]+k[x]);
    }
    else
    {
        siz[x]=1,sum[x]=tmx[x]=k[x];
        lmx[x]=rmx[x]=max(k[x],0);
    }
}

inline void pushdown(int x)
{
    if(rev[x])
    {
        if(ch[x][0]) rever(ch[x][0]);
        if(ch[x][1]) rever(ch[x][1]);
    }
    if(cov[x]!=INF)
    {
        if(ch[x][0]) cover(ch[x][0],cov[x]);
        if(ch[x][1]) cover(ch[x][1],cov[x]);
    }
    rev[x]=0;cov[x]=INF;
}

void split(int now,int w,int &x,int &y)
{
    if(!now) x=y=0;
    else
    {
        pushdown(now);
        if (siz[ch[now][0]]>=w)
            y=now,split(ch[now][0],w,x,ch[now][0]);
        else
            x=now,split(ch[now][1],w-siz[ch[now][0]]-1,ch[now][1],y);
        update(now);
    }
}

int merge(int x,int y)
{
    if(x) pushdown(x);
    if(y) pushdown(y);
    if(x*y==0) return x+y;
    if(tar[x]<tar[y])
    {
        ch[x][1]=merge(ch[x][1],y);
        update(x);return x;
    }
    else
    {
        ch[y][0]=merge(x,ch[y][0]);
        update(y);return y;
    }
}

void trashcol(int x)
{
    if(!x) return;
    trash.push(x);
    trashcol(ch[x][0]);
    trashcol(ch[x][1]);
}

/*
inline void insert()
{
    printf("%d\n",siz[1]);
    int pos=read(),len=read(),x,y;
    int rt=0;
    for(int i=1;i<=len;i++) rt=merge(rt,newnode(read()));
    split(root,pos,x,y);
    root=merge(merge(x,rt),y);
    printf("%d\n",siz[1]);
}

*/

int build(int *data,int n)
{
    int x,last=0;static int sta[N],top;
    for(int i=1;i<=n;i++)
    {
        x=newnode(data[i]),last=0;
        while(top && tar[sta[top]]>tar[x])
            update(sta[top]),last=sta[top],
            sta[top--]=0;
        if (top)
            ch[sta[top]][1]=x;
        ch[x][0]=last,sta[++top]=x;
    }
    while(top)
        update(sta[top--]);
    return sta[1];
}

void insert()
{
    int pos=read(),len=read(),x,y;
    static int datas[N];
    for (int i=1;i<=len;i++)
        datas[i]=read();
    int rt=build(datas,len);
    split(root,pos,x,y);
    root=merge(merge(x,rt),y);
}

inline void delets()
{
    int pos=read(),len=read(),x1,x2,y1,y2;
    split(root,pos-1,x1,x2);
    split(x2,len,y1,y2);
    root=merge(x1,y2);
    trashcol(y1);
}

inline void covers()
{
    int pos=read(),len=read(),v=read(),x1,x2,y1,y2;
    split(root,pos-1,x1,x2);
    split(x2,len,y1,y2);
    cover(y1,v);
    root=merge(x1,merge(y1,y2));
}

inline void reverses()
{
    int pos=read(),len=read(),x1,x2,y1,y2;
    split(root,pos-1,x1,x2);
    split(x2,len,y1,y2);
    rever(y1);
    root=merge(x1,merge(y1,y2));
}

inline void sums()
{
    int pos=read(),len=read(),x1,x2,y1,y2;
    split(root,pos-1,x1,x2);
    split(x2,len,y1,y2);
    printf("%d\n",sum[y1]);
    root=merge(x1,merge(y1,y2));
}

inline void maxs(){printf("%d\n",tmx[root]);}

void work()
{
    char opt[22];
    while(m--) 
    {
        scanf("%s",opt);
        switch (opt[0])
        {
            case 'I':insert();break;
            case 'D':delets();break;
            case 'M':{
                if(opt[2]=='K') covers();
                else maxs();
                break;
            }
            case 'R':reverses();break;
            case 'G':sums();break;
        }
    }   
}

void init()
{
    srand(513);
    n=read(),m=read();static int a[N];
    for (int i=1;i<=n;i++) 
        a[i]=read();
    root=build(a,n); 
    //for(int i=1;i<=n;i++) root=i==1?newnode(read()):merge(root,newnode(read()));
}

int main() 
{ 
    init();
    work();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值