【BZOJ 1500】 维修数列|Splay

就是数据结构题

不过很难调 练码力啦

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
#define N 1000000+100
#define L(x) to[x][0]
#define R(x) to[x][1]
#define I inline 
int n,m,init[N],fa[N],to[N][2],root,size[N],mx[N],ml[N],mr[N],sum[N],num[N],top,q[N];
bool mark[N],ch[N];
I int Read()
{
    char c=getchar();
    int tmp=0,t=1;
    while(c!='-'&&(c<'0'||c>'9')) c=getchar();
    if(c=='-') t=-1,c=getchar();
    while('0'<=c&&c<='9') tmp=tmp*10+c-'0',c=getchar();
    return tmp*t;
} 
I void Up(int x)
{
    int l=L(x),r=R(x);
    size[x]=size[l]+size[r]+1;
    sum[x]=sum[l]+sum[r]+num[x];
    mx[x]=max(max(mx[l],mx[r]),ml[l]+num[x]+mr[r]);
    ml[x]=max(ml[r],sum[r]+num[x]+ml[l]);
    mr[x]=max(mr[l],sum[l]+num[x]+mr[r]);
}
I void Pushdown(int x)
{
    int l=L(x),r=R(x);
    if(ch[x]==true)
    {
        num[l]=num[r]=num[x];
        sum[l]=size[l]*num[x];
        sum[r]=size[r]*num[x];
        if(num[x]<0) ml[l]=ml[r]=mr[l]=mr[r]=0,mx[l]=mx[r]=num[x];
        else mx[l]=ml[l]=mr[l]=sum[l],mx[r]=ml[r]=mr[r]=sum[r];
        ch[l]=ch[r]=true;
        sum[0]=ml[0]=mr[0]=0;
        mx[0]=-100000000;
        ch[x]=mark[x]=false;
    }
    if(mark[x])
    {
        mark[x]=false;
        mark[l]^=1;mark[r]^=1;
        swap(L(l),R(l));swap(L(r),R(r));
        swap(ml[l],mr[l]);swap(ml[r],mr[r]);
    }
}
I void Rotate(int &rt,int x)
{
    int y=fa[x],z=fa[y]; 
    if(y==rt) rt=x;
    else to[z][to[z][1]==y]=x;
    int c=to[y][1]==x;
    fa[x]=z;fa[y]=x;fa[to[x][c^1]]=y;
    to[y][c]=to[x][c^1];to[x][c^1]=y;
    Up(y);Up(x);
}
I void Splay(int &rt,int x)
{
    while(x!=rt)
    {
        if(fa[x]!=rt) Rotate(rt,fa[x]);
        Rotate (rt,x);
    }
}
I int Find(int rt,int x)
{
    Pushdown(rt);
    int tmp=size[L(rt)]+1;
    if(tmp==x)return rt;
    if(tmp<x)return Find(R(rt),x-tmp);
    else return Find(L(rt),x);
}
I void Build(int l,int r)
{
 
    int mid=(l+r)/2;
    int t=q[top--];
    num[t]=init[mid];
    if(l<mid) to[t][0]=q[top],fa[q[top]]=t,Build(l,mid-1);
    if(mid<r) to[t][1]=q[top],fa[q[top]]=t,Build(mid+1,r);
    Up(t);
}
I void Insert(int x,int lenth)
{
    int y=Find(root,x+1);x=Find(root,x);
    Splay(root,x);Splay(R(x),y);
    for(int i=1;i<=lenth;i++)
        init[i]=Read();
    L(y)=q[top];fa[q[top]]=y;
    Build(1,lenth);
    Up(y);Up(x);
}
I void Dfs(int x)
{
    if(x==0)return ;
    Dfs(L(x));Dfs(R(x));
    size[x]=num[x]=fa[x]=L(x)=R(x)=sum[x]=ml[x]=mr[x]=mx[x]=0;
    mark[x]=ch[x]=false;
    q[++top]=x;
}
I void Delate(int x,int lenth)
{
    int y=Find(root,x+lenth);x=Find(root,x-1);
    Splay(root,x);Splay(R(x),y);
    Dfs(L(y));L(y)=0;Up(y);Up(x);
}
I void Change(int x,int lenth,int t)
{
    int y=Find(root,x+lenth);x=Find(root,x-1);
    Splay(root,x);Splay(R(x),y);
    int tmp=L(y);num[tmp]=t;ch[tmp]=true;sum[tmp]=size[tmp]*t;
    if(t<0) ml[tmp]=mr[tmp]=0,mx[tmp]=t;
    else ml[tmp]=mr[tmp]=mx[tmp]=sum[tmp];
    Up(y);Up(x);
}
I void Evert(int x,int lenth)
{
    int y=Find(root,x+lenth);x=Find(root,x-1);
    Splay(root,x);Splay(R(x),y);
    int tmp=L(y);
    mark[tmp]^=1;swap(L(tmp),R(tmp)),swap(ml[tmp],mr[tmp]);
    Up(y),Up(x); 
}
I int Sum(int x,int lenth)
{
    int y=Find(root,x+lenth);x=Find(root,x-1);
    Splay(root,x);Splay(R(x),y);
    return sum[L(y)];
}
int main()
{
    scanf("%d %d",&n,&m);mx[0]=-100000000;
    for(int i=1;i<=1000000;i++) q[i]=1000000-i+1;top=1000000;
    top-=2;fa[1]=2;to[2][0]=1;size[1]=1;size[2]=2;root=2;num[1]=num[2]=-100000000;Up(1);Up(2);
    Insert(1,n);
    char s[200];int x,y,z;
    while(m--)
    {
        scanf("%s",s+1);
        switch(s[3])
        {
            case 'S':x=Read();y=Read();Insert(x+1,y);break;
            case 'L':x=Read();y=Read();Delate(x+1,y);break;
            case 'K':x=Read();y=Read();z=Read();Change(x+1,y,z);break;
            case 'V':x=Read();y=Read();Evert(x+1,y);break;
            case 'T':x=Read();y=Read();printf("%d\n",Sum(x+1,y));break;
            case 'X':printf("%d\n",mx[root]);break;
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值