BZOJ1500: [NOI2005]维修数列

题目链接

Splay终极模板。。注意细节。还是好不熟练哦。

【代码】

#include <cstdio>
#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#define N 1000005 
#define M 200005
#define INF 1e9
#define mod 1000000
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pa;

int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    return x*f;
}

int n,rt,cnt,ans,m;
int son[N][2],fa[N],sz[N],num[N],pos[N],id[N];
int sum[N],mx[N],lx[N],rx[N],a[N];
bool rev[N],tag[N];
queue<int>q;

void pushup(int k)
{
    int l=son[k][0],r=son[k][1];
    sum[k]=sum[l]+sum[r]+num[k];
    sz[k]=sz[l]+sz[r]+1;
    mx[k]=max(max(mx[l],mx[r]),rx[l]+num[k]+lx[r]);
    lx[k]=max(lx[l],sum[l]+lx[r]+num[k]);
    rx[k]=max(rx[r],sum[r]+rx[l]+num[k]);
}

void pushdown(int k)
{
    int l=son[k][0],r=son[k][1];
    if(tag[k])
    {
        rev[k]=tag[k]=0;
        if(l) tag[l]=1,num[l]=num[k],sum[l]=num[l]*sz[l];
        if(r) tag[r]=1,num[r]=num[k],sum[r]=num[r]*sz[r];
        if(num[k]>=0)
        {
            if(l) mx[l]=lx[l]=rx[l]=sum[l];
            if(r) mx[r]=lx[r]=rx[r]=sum[r];
        }
        else
        {
            if(l) lx[l]=rx[l]=0,mx[l]=num[k];
            if(r) lx[r]=rx[r]=0,mx[r]=num[k];
        }
    }
    if(rev[k])
    {
        rev[k]=0;rev[l]^=1,rev[r]^=1;
        swap(lx[l],rx[l]),swap(lx[r],rx[r]);
        swap(son[l][0],son[l][1]);swap(son[r][0],son[r][1]);
    }
}

void Rotate(int x,int &k)
{
    int y=fa[x],z=fa[y],l,r;
    l=son[y][1]==x;r=l^1;
    if(y==k) k=x;
    else son[z][son[z][1]==y]=x;
    fa[x]=z;fa[y]=x;fa[son[x][r]]=y;
    son[y][l]=son[x][r];son[x][r]=y;
    pushup(y);pushup(x);
}

void Splay(int x,int &k)
{
    while(x!=k)
    {
        int y=fa[x],z=fa[y];
        if(y!=k) {
            if(son[z][0]==y^son[y][0]==x) Rotate(x,k);
            else Rotate(y,k);
        }
        Rotate(x,k);
    }
}

int Find(int k,int x)
{
    pushdown(k);
    int l=son[k][0],r=son[k][1];
    if(sz[l]+1==x) return k;
    if(sz[l]+1>x) return Find(l,x);
    return Find(r,x-sz[l]-1);
}

int Spilt(int k,int tot)
{
    int x=Find(rt,k),y=Find(rt,k+tot+1);
    Splay(x,rt);
    Splay(y,son[x][1]);
    return son[y][0];
}

void Build(int l,int r,int f)
{
    if(l>r) return;
    int mid=l+r>>1;int now=id[mid],Last=id[f];
    if(l==r)
    {
        sum[now]=a[l],sz[now]=1;
        tag[now]=rev[now]=0;
        if(a[l]>=0) lx[now]=rx[now]=mx[now]=a[l];
        else lx[now]=rx[now]=0,mx[now]=a[l];
    }
    else Build(l,mid-1,mid),Build(mid+1,r,mid);
    num[now]=a[mid];fa[now]=Last;pushup(now);
    son[Last][mid>f]=now;
}

void Insert(int k,int tot)
{
    for(int i=1;i<=tot;i++) a[i]=read();
    for(int i=1;i<=tot;i++) if(!q.empty()) id[i]=q.front(),q.pop();
    else id[i]=++cnt;
    Build(1,tot,0);int z=id[1+tot>>1];
    int x=Find(rt,k+1),y=Find(rt,k+2);
    Splay(x,rt);Splay(y,son[x][1]);
    fa[z]=y;son[y][0]=z;
    pushup(y);pushup(x);
}

void Change(int k,int tot,int w)
{
    int x=Spilt(k,tot),y=fa[x];
    num[x]=w;tag[x]=1;sum[x]=sz[x]*w;
    if(w>=0) lx[x]=rx[x]=mx[x]=sum[x];
    else lx[x]=rx[x]=0,mx[x]=w;
    pushup(y);pushup(fa[y]);
}

void Reverse(int k,int tot)
{
    int x=Spilt(k,tot),y=fa[x];
    if(!tag[x])
    {
        rev[x]^=1;
        swap(son[x][0],son[x][1]);
        swap(lx[x],rx[x]);pushup(y);pushup(fa[y]);
    }
}

void Del(int k)
{
    if(!k) return;
    int l=son[k][0],r=son[k][1];
    Del(l);Del(r);q.push(k);
    fa[k]=son[k][0]=son[k][1]=0;
    tag[k]=rev[k]=0;
}

void Delete(int k,int tot)
{
    int x=Spilt(k,tot),y=fa[x];
    Del(x);son[y][0]=0;
    pushup(y);pushup(fa[y]);
}

void Query(int k,int tot)
{
    int x=Spilt(k,tot);
    printf("%d\n",sum[x]);
}

void Solve()
{
    while(m--)
    {
        char ch[10];static int x,y;
        scanf("%s",ch);
        if(ch[0]=='M'&&ch[2]=='X')
            printf("%d\n",mx[rt]);
        else
        {
            x=read(),y=read();
            if(ch[0]=='I') Insert(x,y);
            else if(ch[0]=='D') Delete(x,y);
            else if(ch[0]=='M') Change(x,y,read());
            else if(ch[0]=='R') Reverse(x,y);
            else Query(x,y);
        }
    }
}

int main()
{
    n=read();m=read();
    mx[0]=a[1]=a[n+2]=-INF;
    for(int i=1;i<=n;i++) a[i+1]=read();
    for(int i=1;i<=n+2;i++) id[i]=i;
    Build(1,n+2,0);rt=n+3>>1;cnt=n+2;
    Solve();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值