【Splay】bzoj1500(听说此题多码上几遍就能不惧任何平衡树题)

1500: [NOI2005]维修数列

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 15112  Solved: 4996
[Submit][Status][Discuss]

Description

Input

输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目。
第2行包含N个数字,描述初始时的数列。
以下M行,每行一条命令,格式参见问题描述中的表格。
任何时刻数列中最多含有500 000个数,数列中任何一个数字均在[-1 000, 1 000]内。
插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes。

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

 

题解

用Splay进行区间操作的话,就要先把区间的l-1的位置旋转到根,再把r+1旋转成根的子节点

然后r+1的左子树即为所求区间

代码

//by 减维
#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<map>
#include<bitset>
#include<algorithm>
#define ll long long
#define maxn 500005
#define ls son[x][0]
#define rs son[x][1]
#define inf 1<<29
using namespace std;

int n,m,rt,sz,siz[maxn],son[maxn][2],val[maxn],lm[maxn],rm[maxn],ma[maxn],sum[maxn];
int a[maxn],fa[maxn],cov[maxn],mark[maxn];
char ch[25];
queue<int>q;

bool pd(int x){return son[fa[x]][1]==x;}

void upda(int x)
{
    if(!x)return ;
    siz[x]=siz[son[x][0]]+siz[son[x][1]]+1;
    sum[x]=sum[son[x][0]]+sum[son[x][1]]+val[x];
    ma[x]=max(max(0,rm[son[x][0]])+val[x]+max(0,lm[son[x][1]]),max(ma[son[x][0]],ma[son[x][1]]));
    lm[x]=max(sum[son[x][0]]+val[x]+max(0,lm[son[x][1]]),lm[son[x][0]]);
    rm[x]=max(sum[son[x][1]]+val[x]+max(0,rm[son[x][0]]),rm[son[x][1]]);
}

int newnode(int v)
{
    int s;
    if(!q.empty())
        s=q.front(),q.pop();
    else
        s=++sz;
    siz[s]=1;son[s][0]=son[s][1]=fa[s]=mark[s]=0;
    val[s]=sum[s]=ma[s]=lm[s]=rm[s]=v;
    cov[s]=-inf;
    return s;
}

void rotate(int x)
{
    int f=fa[x],g=fa[f],o=pd(x);
    if(g)son[g][pd(f)]=x;
    fa[x]=g;
    son[f][o]=son[x][!o];
    fa[son[f][o]]=f;
    fa[f]=x;son[x][!o]=f;
    upda(f);upda(x);
}

void splay(int x,int tar)
{
    for(;fa[x]!=tar;rotate(x))
        if(fa[fa[x]]!=tar)rotate(pd(fa[x])==pd(x)?fa[x]:x);
    if(tar==0)rt=x;
}

int build(int l,int r)
{
    if(l>r)return 0;
    int mid=(l+r)>>1;
    int v=a[mid];
    int now=newnode(v);
    son[now][0]=build(l,mid-1);
    son[now][1]=build(mid+1,r);
    if(son[now][0])fa[son[now][0]]=now;
    if(son[now][1])fa[son[now][1]]=now;
    upda(now);
    return now;
}

void cover(int x,int v)
{
    if(!x)return ;
    cov[x]=val[x]=v;
    sum[x]=v*siz[x];
    lm[x]=rm[x]=ma[x]=max(v,sum[x]);
}

void rever(int x)
{
    if(!x)return ;
    mark[x]^=1;
    swap(son[x][0],son[x][1]);
    swap(lm[x],rm[x]);
}

void pud(int x)
{
    if(!x)return ;
    if(mark[x]){
        if(son[x][0])rever(son[x][0]);
        if(son[x][1])rever(son[x][1]);
        mark[x]=0;
    }
    if(cov[x]!=-inf){
        if(son[x][0])cover(son[x][0],cov[x]);
        if(son[x][1])cover(son[x][1],cov[x]);
        cov[x]=-inf;
    }
}

int kth(int k)
{
    int x=rt;
    while(1)
    {
        pud(x);
        if(k<=siz[son[x][0]])
            x=son[x][0];
        else if(k==siz[son[x][0]]+1)
            return x;
        else
            k-=siz[son[x][0]]+1,x=son[x][1];
    }
}

void ins()
{
    int pos,num;
    scanf("%d%d",&pos,&num);
    int l=kth(pos+1),r=kth(pos+2);
    splay(l,0);
    splay(r,l);
    for(int i=1;i<=num;++i)scanf("%d",&a[i]);
    int z=build(1,num);
    fa[z]=r;
    son[r][0]=z;
    upda(z),upda(r),upda(l);
}

void delt(int &x)
{
    if(!x)return ;
    q.push(x);
    delt(son[x][0]);
    delt(son[x][1]);
    x=0;
}

void del()
{
    int pos,num;
    scanf("%d%d",&pos,&num);
    int l=kth(pos),r=kth(pos+num+1);
    splay(l,0);splay(r,l);
    delt(son[r][0]);
    upda(r),upda(l);
}

void change()
{
    int pos,num,v;
    scanf("%d%d%d",&pos,&num,&v);
    int l=kth(pos),r=kth(pos+num+1);
    splay(l,0);splay(r,l);
    cover(son[r][0],v);
    upda(r),upda(l);
}

void rev()
{
    int pos,num;
    scanf("%d%d",&pos,&num);
    int l=kth(pos),r=kth(pos+num+1);
    splay(l,0);splay(r,l);
    rever(son[r][0]);
    upda(r),upda(l);
}

void gsum()
{
    int pos,num;
    scanf("%d%d",&pos,&num);
    int l=kth(pos),r=kth(pos+num+1);
    splay(l,0);splay(r,l);
    printf("%d\n",sum[son[r][0]]);
}

void dfs(int x)
{
    if(!x)return ;
    pud(x);
    dfs(son[x][0]);
    printf("%d ",ma[x]);
    dfs(son[x][1]);
}

void dfs2(int x)
{
    if(!x)return ;
    pud(x);
    dfs2(son[x][0]);
    printf("%d ",val[x]);
    dfs2(son[x][1]);
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=2;i<=n+1;++i)scanf("%d",&a[i]);a[1]=a[n+2]=-inf;
    siz[0]=mark[0]=fa[0]=son[0][0]=son[0][1]=0;
    val[0]=ma[0]=lm[0]=rm[0]=-inf;
    rt=build(1,n+2);
    for(int i=1;i<=m;++i)
    {
        scanf("%s",ch);
        if(ch[0]=='M'&&ch[2]=='X'){
            printf("%d\n",ma[rt]);
            continue;
        }
        switch(ch[0]){
            case 'I':ins();break;
            case 'D':del();break;
            case 'M':change();break;
            case 'R':rev();break;
            case 'G':gsum();break;
        }
    }
    return 0;
}

 

posted @ 2017-11-27 18:39  减维  阅读(214)  评论(0编辑  收藏  举报