bzoj1500维修数列——splay

Posted Child-Single

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj1500维修数列——splay相关的知识,希望对你有一定的参考价值。

splay的高级题目,有splay的全部操作,然而本蒟蒻竟不自量力地把这道题作为splay的入门题,然后就学(mi)习(man)了一个星期……

第一次是对着cyc的模版码的,万分感谢><

第二次就自己码了一个小时(弱......)

就作为一个splay学习的模版吧!

技术分享
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
const int maxn=5e5+10,inf=0x3f3f3f3f;
using namespace std;
int n,m,root,a[maxn],A[maxn];
int g[maxn],en[maxn],R[maxn],L[maxn],M[maxn],sum[maxn],s[maxn];
int t[maxn][2],f[maxn]; 
queue<int>q;
int read()
{
    char c=getchar();int ans=0,f=1;
    while(c<0||c>9){if(c==-)f=-1;c=getchar();}
    while(c>=0&&c<=9){ans=ans*10+c-48;c=getchar();}
    return ans*f;
}
void count(int x)
{
    L[x]=max(L[t[x][0]],sum[t[x][0]]+A[x]+max(0,L[t[x][1]]));
    R[x]=max(R[t[x][1]],sum[t[x][1]]+A[x]+max(0,R[t[x][0]]));
    M[x]=max(R[t[x][0]],0)+A[x]+max(0,L[t[x][1]]);
    M[x]=max(M[x],max(M[t[x][0]],M[t[x][1]]));
    sum[x]=sum[t[x][0]]+A[x]+sum[t[x][1]];
    s[x]=s[t[x][0]]+1+s[t[x][1]];
}
void pushdown(int x)
{
    if(g[x])
    {
        g[t[x][0]]^=1;g[t[x][1]]^=1;
        swap(R[t[x][0]],L[t[x][0]]);
        swap(L[t[x][1]],R[t[x][1]]);
        swap(t[x][0],t[x][1]);
        g[x]=0;
    }
    if(en[x])
    {
        if(t[x][0])
        {
            en[t[x][0]]=1;
            A[t[x][0]]=A[x];
            sum[t[x][0]]=s[t[x][0]]*A[x];
            L[t[x][0]]=R[t[x][0]]=M[t[x][0]]=A[x]>0?sum[t[x][0]]:A[x];
        }
        if(t[x][1])
        {
            en[t[x][1]]=1;
            A[t[x][1]]=A[x];
            sum[t[x][1]]=s[t[x][1]]*A[x];
            L[t[x][1]]=R[t[x][1]]=M[t[x][1]]=A[x]>0?sum[t[x][1]]:A[x];
        }
        en[x]=0;
    }
}
void rotate(int x)
{
    int k=x==t[f[x]][1];
    int y=f[x];
    t[y][k]=t[x][!k];f[t[x][!k]]=y;t[x][!k]=y;
    if(f[y])t[f[y]][y==t[f[y]][1]]=x;f[x]=f[y];f[y]=x;
    L[x]=L[y];R[x]=R[y];M[x]=M[y];sum[x]=sum[y];s[x]=s[y];
    count(y);
}
void splay(int x,int r)
{
    for(int fa=f[r];f[x]!=fa;)
    {
        if(f[f[x]]==fa){rotate(x);break;}
        int X=x==t[f[x]][1],Y=f[x]==t[f[f[x]]][1];
        if(X^Y)rotate(x),rotate(x);
            else rotate(f[x]),rotate(x);
    }
}
int node(int fa,int num)
{
    int sz=q.front();q.pop();
    A[sz]=L[sz]=R[sz]=M[sz]=sum[sz]=num;
    s[sz]=1;t[sz][0]=t[sz][1]=g[sz]=en[sz]=0;
    f[sz]=fa;
    return sz;
}
void build(int fa,int &x,int l,int r)
{
    if(l>r)return;
    int mid=(l+r)>>1;
    x=node(fa,a[mid]);
    build(x,t[x][0],l,mid-1);
    build(x,t[x][1],mid+1,r);
    count(x);
}
void find(int &x,int k)
{
    for(int i=x;i;)
    {
        pushdown(i);
        if(k<=s[t[i][0]]){i=t[i][0];continue;}
        if(k==s[t[i][0]]+1){splay(i,x);x=i;break;}
        k-=s[t[i][0]]+1;i=t[i][1];
    }
}
void insert()
{
    int l=read(),k=read();
    for(int i=1;i<=k;i++)a[i]=read();
    int r=0;
    build(0,r,1,k);
    find(root,l+1);find(t[root][1],1);
    t[t[root][1]][0]=r;f[r]=t[root][1];
    count(t[root][1]);count(root);
}
void erase(int x)
{
    if(x)
    {
        q.push(x);
        erase(t[x][0]);
        erase(t[x][1]);
    }
}
void del()
{
    int l=read(),k=read();
    find(root,l);find(t[root][1],k+1);
    erase(t[t[root][1]][0]);
    t[t[root][1]][0]=0;
    count(t[root][1]);count(root);
}
void cover()
{
    int l=read(),k=read(),num=read();
    find(root,l);find(t[root][1],k+1);
    int y=t[t[root][1]][0];
    en[y]=1;A[y]=num;
    sum[y]=s[y]*A[y];
    R[y]=L[y]=M[y]=A[y]>0?sum[y]:A[y];
    count(t[root][1]);count(root);
}
void turn()
{
    int l=read(),k=read();
    find(root,l);find(t[root][1],k+1);
    int y=t[t[root][1]][0];
    g[y]^=1;
    swap(R[y],L[y]);
    count(t[root][1]);count(root);
}
void get_sum()
{
    int l=read(),k=read();
    find(root,l);find(t[root][1],k+1);
    printf("%d\n",sum[t[t[root][1]][0]]);
}
void get_m()
{
    int sz=s[root];
    find(root,1);find(t[root][1],sz-1);
    printf("%d\n",M[t[t[root][1]][0]]);
}
int main()
{
    n=read();m=read();
    a[0]=a[n+1]=0;root=0;
    L[0]=R[0]=M[0]=-inf;
    for(int i=1;i<=maxn;i++)q.push(i);
    for(int i=1;i<=n;i++)a[i]=read();
    build(0,root,0,n+1);
    char str[20];
    for(int i=1;i<=m;i++)
    {
        scanf("%s",str);
        if(str[2]==S)insert();
        else if(str[2]==L)del();
        else if(str[2]==K)cover();
        else if(str[2]==V)turn();
        else if(str[2]==T)get_sum();
        else if(str[2]==X)get_m();
    }
    return 0;
}
bzoj1500

 

以上是关于bzoj1500维修数列——splay的主要内容,如果未能解决你的问题,请参考以下文章

bzoj1500维修数列——splay

BZOJ1500 [NOI2005]维修数列 splay

[bzoj1500][NOI2005 维修数列] (splay区间操作)

bzoj1500: [NOI2005]维修数列

BZOJ1500: [NOI2005]维修数列

bzoj1500 [NOI2005]维修数列