JZOJ 2413. 【NOI2005】维护数列

Description

  请写一个程序,要求维护一个数列,支持以下6种操作:(请注意,格式栏中的下划线‘ _ ’表示实际输入文件中的空格)
  1. 插入 INSERT_posi_tot_c1_c2_…_ctot 在当前数列的第posi个数字后插入tot个数字:c1, c2, …, ctot;若在数列首插入,则posi为0
  2. 删除 DELETE_posi_tot 从当前数列的第posi个数字开始连续删除tot个数字
  3. 修改 MAKE-SAME_posi_tot_c 将当前数列的第posi个数字开始的连续tot个数字统一修改为c
  4. 翻转 REVERSE_posi_tot 取出从当前数列的第posi个数字开始的tot个数字,翻转后放入原来的位置
  5. 求和 GET-SUM_posi_tot 计算从当前数列开始的第posi个数字开始的tot个数字的和并输出
  6. 求和最大的子列 MAX-SUM 求出当前数列中和最大的一段子列,并输出最大和

Input

  输入文件的第1行包含两个数N和M,N表示初始时数列中数的个数,M表示要进行的操作数目。
  第2行包含N个数字,描述初始时的数列。
  以下M行,每行一条命令,格式参见问题描述中的表格。

Output

   对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。

Sample Input

9 8
2 -6 3 5 1 -5 -3 6 3
GET-SUM 5 4
MAX-SUM
INSERT 8 3 -5 7 2
DELETE 12 1
MAKE-SAME 3 3 2
REVERSE 3 6
GET-SUM 5 4
MAX-SUM

Sample Output

-1
10
1
10

Data Constraint

Hint

样例说明请点这里
【数据规模和约定】
  你可以认为在任何时刻,数列中至少有1个数。
  输入数据一定是正确的,即指定位置的数在数列中一定存在。
  50%的数据中,任何时刻数列中最多含有30 000个数;
  100%的数据中,任何时刻数列中最多含有500 000个数。
  100%的数据中,任何时刻数列中任何一个数字均在[-1 000, 1 000]内。
  100%的数据中,M ≤20 000,插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes。

Solution

  • 这题真的调试了一万年……

  • 经典的Splay操作,维护子序列的话就维护一下子树前后缀的最大值,在合并到父亲上即可。

Code

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=5e5+3,inf=1e9;
int root,tot;
int a[N],fa[N],key[N],size[N],s[N][2];
int sum[N],c[N],mx[N],pre[N],suf[N],back[N];
bool rev[N];
inline int read()
{
    int X=0,w=1; char ch=0;
    while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();
    return X*w;
}
inline void write(int x)
{
    if(x<0) x=-x,putchar('-');
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
inline int max(int x,int y)
{
    return x>y?x:y;
}
inline bool pd(int x)
{
    return x==s[fa[x]][1];
}
inline void newnode(int &v,int val,int p)
{
    if(back[0]) v=back[back[0]--]; else v=++tot;
    sum[v]=mx[v]=key[v]=val;
    pre[v]=suf[v]=max(0,val);
    size[v]=1,fa[v]=p,c[v]=inf;
    s[v][0]=s[v][1]=rev[v]=0;
}
inline void reverse(int v)
{
    if(!v) return;
    swap(s[v][0],s[v][1]);
    swap(pre[v],suf[v]);
    rev[v]^=1;
}
inline void modify(int v,int val)
{
    if(!v) return;
    sum[v]=size[v]*val,c[v]=key[v]=val;
    if(val>0) mx[v]=pre[v]=suf[v]=sum[v]; else
        pre[v]=suf[v]=0,mx[v]=val;
}
inline void update(int v)
{
    sum[v]=sum[s[v][0]]+sum[s[v][1]]+key[v];
    size[v]=size[s[v][0]]+size[s[v][1]]+1;
    pre[v]=max(pre[s[v][0]],sum[s[v][0]]+key[v]+pre[s[v][1]]);
    suf[v]=max(suf[s[v][1]],sum[s[v][1]]+key[v]+suf[s[v][0]]);
    mx[v]=max(0,suf[s[v][0]])+key[v]+max(0,pre[s[v][1]]);
    if(s[v][0]) mx[v]=max(mx[v],mx[s[v][0]]);
    if(s[v][1]) mx[v]=max(mx[v],mx[s[v][1]]);
}
inline void down(int v)
{
    if(rev[v])
    {
        reverse(s[v][0]),reverse(s[v][1]);
        rev[v]=false;
    }
    if(c[v]<inf)
    {
        modify(s[v][0],c[v]),modify(s[v][1],c[v]);
        c[v]=inf;
    }
}
inline void build(int &v,int l,int r,int p)
{
    if(l>r) return;
    int mid=(l+r)>>1;
    newnode(v,a[mid],p);
    build(s[v][0],l,mid-1,v);
    build(s[v][1],mid+1,r,v);
    update(v);
}
inline void rotate(int x)
{
    down(x);
    int y=fa[x],w=pd(x);
    if(s[y][w]=s[x][w^1]) fa[s[x][w^1]]=y;
    if(fa[x]=fa[y]) s[fa[y]][pd(y)]=x;
    s[fa[y]=x][w^1]=y;
    update(y);
}
inline void splay(int x,int k)
{
    for(int y;(y=fa[x])^k;rotate(x))
        if(fa[y]^k) rotate(pd(x)==pd(y)?y:x);
    update(x);
    if(!k) root=x;
}
inline int kth(int v,int k)
{
    down(v);
    if(size[s[v][0]]+1==k) return v;
    if(k<=size[s[v][0]]) return kth(s[v][0],k);
    return kth(s[v][1],k-size[s[v][0]]-1);
}
inline void change(int l,int r,int val)
{
    splay(kth(root,l-1),0);
    splay(kth(root,r+1),root);
    modify(s[s[root][1]][0],val);
}
inline int get_sum(int l,int r)
{
    splay(kth(root,l-1),0);
    splay(kth(root,r+1),root);
    return sum[s[s[root][1]][0]];
}
inline void insert(int x,int y)
{
    splay(kth(root,x),0);
    splay(kth(root,x+1),root);
    build(s[s[root][1]][0],1,y,s[root][1]);
    update(s[root][1]),update(root);
}
inline void travel(int v)
{
    down(v);
    if(s[v][0]) travel(s[v][0]);
    back[++back[0]]=v;
    if(s[v][1]) travel(s[v][1]);
}
inline void delete_num(int x,int y)
{
    splay(kth(root,x-1),0);
    splay(kth(root,y+1),root);
    travel(s[s[root][1]][0]);
    s[s[root][1]][0]=0;
    update(s[root][1]),update(root);
}
inline void flip(int l,int r)
{
    splay(kth(root,l-1),0);
    splay(kth(root,r+1),root);
    reverse(s[s[root][1]][0]);
}
inline int get_max(int l,int r)
{
    splay(kth(root,l-1),0);
    splay(kth(root,r+1),root);
    return mx[s[s[root][1]][0]];
}
inline void print(int v)
{
    down(v);
    if(s[v][0]) print(s[v][0]);
    if(key[v]<inf) write(key[v]),putchar(' ');
    if(s[v][1]) print(s[v][1]);
}
int main()
{
    int n=read(),m=read();
    a[1]=a[n+2]=-inf,c[0]=inf;
    for(int i=2;i<=n+1;i++) a[i]=read();
    build(root,1,n+2,0);
    while(m--)
    {
        char ch=getchar();
        while(ch!='X' && ch!='G' && ch!='V' && ch!='I' && ch!='D' && ch!='K') ch=getchar();
        if(ch=='K')//MAKE-SAME
        {
            getchar(),getchar();
            int x=read()+1,y=x+read()-1;
            change(x,y,read());
        }else
        if(ch=='G')//GET-SUM
        {
            getchar(),getchar(),getchar();
            int x=read()+1,y=x+read()-1;
            write(get_sum(x,y)),putchar('\n');
        }else
        if(ch=='I')//INSERT
        {
            int x=read()+1,y=read();
            for(int i=1;i<=y;i++) a[i]=read();
            insert(x,y);
        }else
        if(ch=='D')//DELETE
        {
            int x=read()+1,y=x+read()-1;
            delete_num(x,y); 
        }else
        if(ch=='V')//REVERSE
        {
            int x=read()+1,y=x+read()-1;
            flip(x,y);
        }else
        if(ch=='X')//MAX-SUM
        {
            write(get_max(2,size[root]-1)),putchar('\n');
            scanf("\n");
        }
    }
    return 0;
}

Code

//新打的,更快的,更短的

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
using namespace std;
const int N=5e5+5,inf=1e9;
int root,tot;
int fa[N],s[N][2],key[N],size[N];
int pre[N],suf[N],sum[N],mx[N],c[N];
int a[N],back[N];
bool rev[N];
char st[10];
inline int read()
{
    int X=0,w=0; char ch=0;
    while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}
inline void write(int x)
{
    if(x<0) x=-x,putchar('-');
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
inline int max(int x,int y)
{
    return x>y?x:y;
}
inline bool pd(int x)
{
    return x==s[fa[x]][1];
}
inline void update(int x)
{
    sum[x]=sum[s[x][0]]+sum[s[x][1]]+key[x];
    size[x]=size[s[x][0]]+size[s[x][1]]+1;
    pre[x]=max(pre[s[x][0]],sum[s[x][0]]+key[x]+pre[s[x][1]]);
    suf[x]=max(suf[s[x][1]],sum[s[x][1]]+key[x]+suf[s[x][0]]);
    mx[x]=max(0,suf[s[x][0]])+key[x]+max(0,pre[s[x][1]]);
    if(s[x][0]) mx[x]=max(mx[x],mx[s[x][0]]);
    if(s[x][1]) mx[x]=max(mx[x],mx[s[x][1]]);
}
inline void newnode(int &v,int val,int p)
{
    if(back[0]) v=back[back[0]--]; else v=++tot;
    key[v]=sum[v]=mx[v]=val;
    fa[v]=p,size[v]=1,c[v]=inf;
    pre[v]=suf[v]=max(0,val);
    s[v][0]=s[v][1]=rev[v]=0;
}
void build(int &v,int l,int r,int p)
{
    if(l>r) return;
    int mid=l+r>>1;
    newnode(v,a[mid],p);
    build(s[v][0],l,mid-1,v);
    build(s[v][1],mid+1,r,v);
    update(v);
}
inline void reverse(int x)
{
    if(!x) return;
    swap(s[x][0],s[x][1]);
    swap(pre[x],suf[x]);
    rev[x]^=1;
}
inline void modify(int x,int val)
{
    if(!x) return;
    sum[x]=size[x]*val,key[x]=c[x]=val;
    if(val>0) pre[x]=suf[x]=mx[x]=sum[x]; else
        pre[x]=suf[x]=0,mx[x]=val;
}
inline void down(int x)
{
    if(rev[x])
    {
        reverse(s[x][0]),reverse(s[x][1]);
        rev[x]=false;
    }
    if(c[x]<inf)
    {
        modify(s[x][0],c[x]),modify(s[x][1],c[x]);
        c[x]=inf;
    }
}
inline void rotate(int x)
{
    down(x);
    int y=fa[x],w=pd(x);
    if(s[y][w]=s[x][w^1]) fa[s[y][w]]=y;
    if(fa[x]=fa[y]) s[fa[y]][pd(y)]=x;
    s[fa[y]=x][w^1]=y;
    update(y);
}
inline void splay(int x,int k)
{
    for(int y;(y=fa[x])^k;rotate(x))
        if(fa[y]^k) rotate(pd(x)==pd(y)?y:x);
    update(x);
    if(!k) root=x;
}
int kth(int x,int k)
{
    down(x);
    if(size[s[x][0]]+1==k) return x;
    if(size[s[x][0]]>=k) return kth(s[x][0],k);
    return kth(s[x][1],k-size[s[x][0]]-1);
}
inline void get(int x,int y)
{
    splay(kth(root,x-1),0);
    splay(kth(root,y+1),root);
}
void travel(int x)
{
    if(s[x][0]) travel(s[x][0]);
    back[++back[0]]=x;
    if(s[x][1]) travel(s[x][1]);
}
int main()
{
    int n=read(),m=read();
    a[1]=a[n+2]=inf;
    for(int i=2;i<=n+1;i++) a[i]=read();
    build(root,1,n+2,0);
    while(m--)
    {
        scanf("%s",&st);
        if(st[0]=='I')
        {
            int x=read()+1,y=read();
            for(int i=1;i<=y;i++) a[i]=read();
            splay(kth(root,x),0);
            splay(kth(root,x+1),root);
            build(s[s[root][1]][0],1,y,s[root][1]);
            update(s[root][1]),update(root);
        }else
        if(st[0]=='D')
        {
            int x=read()+1,y=x+read()-1;
            get(x,y);
            travel(s[s[root][1]][0]);
            s[s[root][1]][0]=0;
            update(s[root][1]),update(root);
        }else
        if(st[0]=='R')
        {
            int x=read()+1,y=x+read()-1;
            get(x,y);
            reverse(s[s[root][1]][0]);
        }else
        if(st[0]=='G')
        {
            int x=read()+1,y=x+read()-1;
            get(x,y);
            write(sum[s[s[root][1]][0]]),putchar('\n');
        }else
        if(st[2]=='K')
        {
            int x=read()+1,y=x+read()-1,z=read();
            get(x,y);
            modify(s[s[root][1]][0],z);
        }else
        {
            get(2,size[root]-1);
            write(mx[s[s[root][1]][0]]),putchar('\n');
        }
    }
    return 0;
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值