您的位置:首页 > 其它

伸展树(插入区间,修改区间,区间置数,区间反转,区间求和,连续最大和)BZOJ1500

2014-11-30 17:20 369 查看

1500: [NOI2005]维修数列

Time Limit: 10 Sec Memory Limit:
64 MB

Submit: 6678 Solved: 2018

[Submit][Status]

Description



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

HINT



Source

splay

区间插入删除,反转,求和就不说了,前几篇博客都有

区间修改:setv表示该区间是不是被修改过,修改的时候把区间key修改,往下pushdown的时候根据key修改即可

最大字段和:保存一个左边连续最大,右边连续最大,区间连续最大,想线段树一样就行更新

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
#define Key_value ch[ch[root][1]][0]
using namespace std;
const int maxn=500010;
const int INF=1000000000;
int a[maxn],N,M;
int ch[maxn][2],pre[maxn],size[maxn],key[maxn],rev[maxn];
int sum[maxn],setv[maxn];
int root,tot1,tot2,s[maxn];
int lx[maxn],rx[maxn],mx[maxn];
void NewNode(int &r,int f,int val)
{
    if(tot2)r=s[tot2--];
    else r=++tot1;
    ch[r][0]=ch[r][1]=0;
    pre[r]=f;
    key[r]=val;
    rev[r]=setv[r]=0;
    sum[r]=val;
    size[r]=1;
    lx[r]=rx[r]=mx[r]=val;
}
void update_setv(int r,int c)
{
    if(!r)return;
    setv[r]=1;
    key[r]=c;
    sum[r]=size[r]*c;
    lx[r]=rx[r]=mx[r]=max(c,c*size[r]);
}
void pushup(int r)
{
    int lc=ch[r][0],rc=ch[r][1];
    size[r]=size[lc]+size[rc]+1;
    sum[r]=sum[rc]+sum[lc]+key[r];
    lx[r]=max(lx[lc],sum[lc]+key[r]+max(0,lx[rc]));
    rx[r]=max(rx[rc],sum[rc]+key[r]+max(0,rx[lc]));
    mx[r]=max(mx[lc],mx[rc]);
    mx[r]=max(mx[r],max(0,rx[lc])+key[r]+max(0,lx[rc]));
}
void update_rev(int r)
{
    if(!r)return;
    swap(ch[r][0],ch[r][1]);
    swap(lx[r],rx[r]);
    rev[r]^=1;
}
void pushdown(int r)
{
    if(setv[r])
    {
        update_setv(ch[r][0],key[r]);
        update_setv(ch[r][1],key[r]);
        setv[r]=0;
    }
    if(rev[r])
    {
        update_rev(ch[r][0]);
        update_rev(ch[r][1]);
        rev[r]=0;
    }

}
void build(int &x,int l,int r,int f)
{
    if(l>r)return ;
    int mid=(l+r)>>1;
    NewNode(x,f,a[mid]);
    build(ch[x][0],l,mid-1,x);
    build(ch[x][1],mid+1,r,x);
    pushup(x);
}
void init()
{
    root=tot1=tot2=0;
    ch[root][0]=ch[root][1]=size[root]=key[root]=pre[root]=0;
    sum[root]=rev[root]=0;lx[root]=rx[root]=mx[root]=-INF;
    NewNode(root,0,-1);
    NewNode(ch[root][1],root,-1);
    build(Key_value,1,N,ch[root][1]);
    pushup(ch[root][1]);
    pushup(root);
}
void Rotate(int x,int kind)
{
    int y=pre[x];
    pushdown(y);
    pushdown(x);
    ch[y][!kind]=ch[x][kind];
    pre[ch[x][kind]]=y;
    if(pre[y])ch[pre[y]][ch[pre[y]][1]==y]=x;
    pre[x]=pre[y];
    ch[x][kind]=y;
    pre[y]=x;
    pushup(y);
}
void Splay(int r,int goal)
{
    pushdown(r);
    while(pre[r]!=goal)
    {
        if(pre[pre[r]]==goal)
        {
            pushdown(pre[r]);
            pushdown(r);
            Rotate(r,ch[pre[r]][0]==r);
        }
        else
        {
            pushdown(pre[pre[r]]);
            pushdown(pre[r]);
            pushdown(r);
            int y=pre[r];
            int kind=(ch[pre[y]][0]==y);
            if(ch[y][kind]==r)
            {
                Rotate(r,!kind);
                Rotate(r,kind);
            }
            else
            {
                Rotate(y,kind);
                Rotate(r,kind);
            }
        }
    }
    pushup(r);
    if(goal==0)root=r;
}
int get_kth(int r,int k)
{
    pushdown(r);
    int t=size[ch[r][0]]+1;
    if(t==k)return r;
    if(t>k)return get_kth(ch[r][0],k);
    else return get_kth(ch[r][1],k-t);
}
void Insert(int pos,int tot)
{
    Splay(get_kth(root,pos+1),0);
    Splay(get_kth(root,pos+2),root);
    build(Key_value,1,tot,ch[root][1]);
    pushup(ch[root][1]);
    pushup(root);
}
void erase(int r)
{
    if(r)
    {
        s[++tot2]=r;
        erase(ch[r][0]);
        erase(ch[r][1]);
    }
}
void Delete(int pos,int tot)
{
    Splay(get_kth(root,pos),0);
    Splay(get_kth(root,pos+1+tot),root);
    erase(Key_value);
    pre[Key_value]=0;
    Key_value=0;
    pushup(ch[root][1]);
    pushup(root);
}
void MakeSame(int pos,int tot,int c)
{
    Splay(get_kth(root,pos),0);
    Splay(get_kth(root,pos+1+tot),root);
    update_setv(Key_value,c);
    pushup(ch[root][1]);
    pushup(root);
}
void Reverse(int pos,int tot)
{
    Splay(get_kth(root,pos),0);
    Splay(get_kth(root,pos+1+tot),root);
    update_rev(Key_value);
    pushup(ch[root][1]);
    pushup(root);
}
void GetSum(int pos,int tot)
{
    Splay(get_kth(root,pos),0);
    Splay(get_kth(root,pos+1+tot),root);
    pushup(ch[root][1]);
    pushup(root);
    printf("%d\n",sum[Key_value]);
}
void MaxSum(int pos,int tot)
{
    Splay(get_kth(root,pos),0);
    Splay(get_kth(root,pos+1+tot),root);
    printf("%d\n",mx[Key_value]);
}
int main()
{
    char op[20];
    int pos,tot,c;
    while(scanf("%d%d",&N,&M)!=EOF)
    {
        for(int i=1;i<=N;i++)scanf("%d",&a[i]);
        init();
        while(M--)
        {
            scanf("%s",op);
            if(op[0]=='I')
            {
                scanf("%d%d",&pos,&tot);
                for(int i=1;i<=tot;i++)
                    scanf("%d",&a[i]);
                Insert(pos,tot);
            }
            else if(op[0]=='D')
            {
                scanf("%d%d",&pos,&tot);
                Delete(pos,tot);
            }
            else if(!strcmp(op,"MAKE-SAME"))
            {
                scanf("%d%d%d",&pos,&tot,&c);
                MakeSame(pos,tot,c);
            }
            else if(op[0]=='R')
            {
                scanf("%d%d",&pos,&tot);
                Reverse(pos,tot);
            }
            else if(op[0]=='G')
            {
                scanf("%d%d",&pos,&tot);
                GetSum(pos,tot);
            }
            else MaxSum(1,size[root]-2);
        }
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: