大視野在線測評 1500 [NOI2005]維修數列(splay)

題目鏈接

1500: [NOI2005]維修數列

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 8379  Solved: 2521
[Submit][Status][Discuss]

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

題解:要操作區間 [ L,R ] 。把第L-1個點伸展的根,把第R+1個點伸展到根下面,那麼第R+1個點的左子樹就是區間[ L , R ] 。跟線段樹區間操作類似,對區間打上延時標記即可。

對於插入操作來說,先將插入序列建成一個完全二叉樹,然後再插入對應位置即可

對於刪除操作來說,先將對應區間伸展出來,刪除即可

對於詢問區間和,我們維護每個子樹的和

對於詢問最大連續子區間來說,我們還要維護區間的以做端點爲起點的最大連續和,以右端點爲起點的最大連續和,已經區間最大連續和。

詳情和參加論文:運用伸展樹解決數列維護問題

代碼如下:

#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<string.h>
#include<string>
typedef long long LL;
const int inf=0x3fffffff;
const int nn=210000;
using namespace std;
struct node
{
    int val;
    int cnt;
    LL sum;
    LL asum,lsum,rsum;
    int xg;
    bool fz;
    node* pre;
    node* ch[2];
}*root;
void fz(node* o)
{
    swap(o->ch[0],o->ch[1]);
    swap(o->lsum,o->rsum);
}
void fg(node* o,LL val)
{
    o->val=val;
    o->sum=val*o->cnt;
    if(val>0)
        o->asum=o->lsum=o->rsum=o->sum;
    else
        o->asum=o->lsum=o->rsum=val;
}
void push_down(node* o)
{
    if(o==NULL)
        return ;
    if(o->xg!=inf)
    {
        if(o->ch[0]!=NULL)
        {
            o->ch[0]->xg=o->xg;
            fg(o->ch[0],o->xg);
        }
        if(o->ch[1]!=NULL)
        {
            o->ch[1]->xg=o->xg;
            fg(o->ch[1],o->xg);
        }
        o->xg=inf;
    }
    if(o->fz)
    {
        if(o->ch[0]!=NULL)
        {
            o->ch[0]->fz=!o->ch[0]->fz;
            fz(o->ch[0]);
        }
        if(o->ch[1]!=NULL)
        {
            o->ch[1]->fz=!o->ch[1]->fz;
            fz(o->ch[1]);
        }
        o->fz=false;
    }
}
void push_up(node* o)
{
    if(o==NULL)
        return ;
    push_down(o);
    o->cnt=1;
    o->sum=o->val;
    if(o->ch[0]!=NULL)
    {
        o->cnt+=o->ch[0]->cnt;
        o->sum+=o->ch[0]->sum;
    }
    if(o->ch[1]!=NULL)
    {
        o->cnt+=o->ch[1]->cnt;
        o->sum+=o->ch[1]->sum;
    }
    if(o->ch[0]!=NULL&&o->ch[1]!=NULL)
    {
        o->asum=max(o->ch[0]->asum,o->ch[1]->asum);
        o->asum=max(o->asum,(LL)o->val);
        o->asum=max(o->asum,o->ch[0]->rsum+o->val);
        o->asum=max(o->asum,o->ch[1]->lsum+o->val);
        o->asum=max(o->asum,o->ch[0]->rsum+o->val+o->ch[1]->lsum);
        o->lsum=max(o->ch[0]->lsum,o->ch[0]->sum+o->val);
        o->lsum=max(o->lsum,o->ch[0]->sum+o->val+o->ch[1]->lsum);
        o->rsum=max(o->ch[1]->rsum,o->ch[1]->sum+o->val);
        o->rsum=max(o->rsum,o->ch[1]->sum+o->val+o->ch[0]->rsum);
    }
    else if(o->ch[0]!=NULL&&o->ch[1]==NULL)
    {
        o->asum=max(o->ch[0]->asum,(LL)o->val);
        o->asum=max(o->asum,o->val+o->ch[0]->rsum);
        o->lsum=max(o->ch[0]->lsum,o->ch[0]->sum+o->val);
        o->rsum=max((LL)o->val,o->val+o->ch[0]->rsum);
    }
    else if(o->ch[0]==NULL&&o->ch[1]!=NULL)
    {
        o->asum=max(o->ch[1]->asum,(LL)o->val);
        o->asum=max(o->asum,o->val+o->ch[1]->lsum);
        o->lsum=max((LL)o->val,o->val+o->ch[1]->lsum);
        o->rsum=max(o->ch[1]->rsum,o->val+o->ch[1]->sum);
    }
    else
        o->asum=o->lsum=o->rsum=o->val;
}
void Rotate(node* o)
{
    node* tem=o->pre;
    push_down(tem);
    push_down(o);
    int d;
    if(tem->ch[0]==o) d=0;
    else d=1;
    tem->ch[d]=o->ch[d^1];
    if(o->ch[d^1]!=NULL)
        o->ch[d^1]->pre=tem;
    if(tem->pre!=NULL)
    {
        if(tem->pre->ch[0]==tem)
            tem->pre->ch[0]=o;
        else
            tem->pre->ch[1]=o;
    }
    o->pre=tem->pre;
    o->ch[d^1]=tem;
    tem->pre=o;
    push_up(tem);
}
void Splay(node* o,node* f)
{
    node* x;
    node* y;
    int d1,d2;
    while(o->pre!=f)
    {
        if(o->pre->pre==f)
            Rotate(o);
        else
        {
            x=o->pre;
            y=x->pre;
            if(y->ch[0]==x) d1=0;
            else d1=1;
            if(x->ch[0]==o) d2=0;
            else d2=1;
            if(d1==d2)
            {
                Rotate(x);
                Rotate(o);
            }
            else
            {
                Rotate(o);
                Rotate(o);
            }
        }
    }
    push_up(o);
    if(f==NULL)
        root=o;
}
node* select(node* o,int k,node* f)
{
    push_down(o);
    int tem=0;
    if(o->ch[0]!=NULL)
    {
        tem+=o->ch[0]->cnt;
    }
    if(tem>=k)
        return select(o->ch[0],k,f);
    else if(tem+1==k)
    {
        Splay(o,f);
        return o;
    }
    else
        return select(o->ch[1],k-tem-1,f);
}
node* build(node* pre,int *a,int l,int r)
{
    node* re;
    re=new node;
    int mid=(l+r)/2;
    re->val=a[mid];
    re->pre=pre;
    re->fz=false;
    re->xg=inf;
    re->ch[0]=re->ch[1]=NULL;
    if(l==r)
    {
        push_up(re);
        return re;
    }
    if(l<=mid-1)
        re->ch[0]=build(re,a,l,mid-1);
    re->ch[1]=build(re,a,mid+1,r);
    push_up(re);
    return re;
}
void Clear(node* &o)
{
    if(o==NULL)
        return ;
    Clear(o->ch[0]);
    Clear(o->ch[1]);
    delete o;
    o=NULL;
}
void Insert(int L,int R,int *a,int l,int r)
{
    node* x=select(root,L,NULL);
    node* y=select(root,R,x);
    push_down(y);
    y->ch[0]=build(y,a,l,r);
    Splay(y->ch[0],NULL);
}
void Remove(int L,int R)
{
    node* x=select(root,L-1,NULL);
    node* y=select(root,R+1,x);
    push_down(y);
    Clear(y->ch[0]);
    Splay(y,NULL);
}
void Change(int L,int R,int c)
{
    node* x=select(root,L-1,NULL);
    node* y=select(root,R+1,x);
    push_down(y);
    y->ch[0]->xg=c;
    fg(y->ch[0],c);
    Splay(y->ch[0],NULL);
}
void Fanzhuan(int L,int R)
{
    node* x=select(root,L-1,NULL);
    node* y=select(root,R+1,x);
    push_down(y);
    y->ch[0]->fz=!y->ch[0]->fz;
    fz(y->ch[0]);
    Splay(y->ch[0],NULL);
}
LL Getsum(int L,int R)
{
    if(L>R)
        return 0;
    node* x=select(root,L-1,NULL);
    node* y=select(root,R+1,x);
    push_down(y);
    return y->ch[0]->sum;
}
LL Getsum2(int L,int R)
{
    if(L>R)
        return 0;
    node* x=select(root,L-1,NULL);
    node* y=select(root,R+1,x);
    push_down(y);
    return y->ch[0]->asum;
}
int n,m;
int a[nn];
void init()
{
    root=NULL;
    root=new node;
    root->fz=false;
    root->xg=inf;
    root->val=0;
    root->cnt=2;
    root->pre=NULL;
    root->asum=root->sum=root->lsum=root->rsum=0;
    root->ch[0]=NULL;
    root->ch[1]=NULL;

    root->ch[1]=new node;
    root->ch[1]->val=0;
    root->ch[1]->cnt=1;
    root->ch[1]->asum=root->ch[1]->lsum=root->ch[1]->rsum=root->ch[1]->sum=0;
    root->ch[1]->pre=root;
    root->ch[1]->fz=false;
    root->ch[1]->xg=inf;
    root->ch[1]->ch[0]=root->ch[1]->ch[1]=NULL;
}
int main()
{
    int i;
    char s[10];
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        init();
        for(i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        if(n>=1)
            Insert(1,2,a,1,n);
        int pos,tot,c;
        while(m--)
        {
            scanf("%s",s);
            if(strcmp(s,"INSERT")==0)
            {
                scanf("%d%d",&pos,&tot);
                if(tot==0)
                    continue;
                for(i=1;i<=tot;i++)
                {
                    scanf("%d",&a[i]);
                }
                Insert(pos+1,pos+2,a,1,tot);
            }
            else if(strcmp(s,"DELETE")==0)
            {
                scanf("%d%d",&pos,&tot);
                if(tot==0)
                    continue;
                Remove(pos+1,pos+tot);
            }
            else if(strcmp(s,"MAKE-SAME")==0)
            {
                scanf("%d%d%d",&pos,&tot,&c);
                if(tot==0)
                    continue;
                Change(pos+1,pos+tot,c);
            }
            else if(strcmp(s,"REVERSE")==0)
            {
                scanf("%d%d",&pos,&tot);
                if(tot==0)
                    continue;
                Fanzhuan(pos+1,pos+tot);
            }
            else if(strcmp(s,"GET-SUM")==0)
            {
                scanf("%d%d",&pos,&tot);
                printf("%lld\n",Getsum(pos+1,pos+tot));
            }
            else if(strcmp(s,"MAX-SUM")==0)
            {
                printf("%lld\n",Getsum2(2,root->cnt-1));
            }
        }
        Clear(root);
    }
    return 0;
}


發佈了213 篇原創文章 · 獲贊 4 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章