zoukankan      html  css  js  c++  java
  • 【fhq Treap】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

    题解

    非常恶心的一道题。。。

    用fhq Treap完成的话

    1、把原有的平衡树从pos处拆开,把新加的点新建一颗小平衡树合并进去

    2、把原有平衡树从pos和pos+num处拆开,合并左右中间不要【但是记得回收下标】

    3、把原有平衡树从pos和pos+num处拆开,在中间打上标记cov

    4、把原有平衡树从pos和pos+num处拆开,在中间打上标记mark

    5、把原有平衡树从pos和pos+num处拆开,输出sum[中间]

    6、输出ma[rt];

    【注意fhq Treap的lazy标记和线段树的不一样,线段树的标记是标而不改,fhq Treap是标时即改,不然在split和merge时可能不会改变之前标记的根节点】

    注:spli是我校大神,用函数名调戏一下他hhh

    代码

    //by 减维
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<queue>
    #include<cstdlib>
    #include<ctime>
    #include<cmath>
    #include<map>
    #include<bitset>
    #include<algorithm>
    #define inf 1<<30
    #define ll long long
    using namespace std;
     
    int n,m,rt,sz,siz[500005],son[500005][2],val[500005],lm[500005],rm[500005],ma[500005],sum[500005],mark[500005],cov[500005],pri[500005];
    int a[200005];
    char ch[25];
    queue<int>q;
     
    int newnode(int v)
    {
        int x;
        if(!q.empty())
            x=q.front(),q.pop();
        else x=++sz;
        siz[x]=1;
        son[x][0]=son[x][1]=mark[x]=0;
        cov[x]=inf;pri[x]=rand();
        val[x]=sum[x]=ma[x]=v;
        lm[x]=rm[x]=v;
        return 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(lm[son[x][0]],sum[son[x][0]]+val[x]+max(0,lm[son[x][1]]));
        rm[x]=max(rm[son[x][1]],sum[son[x][1]]+val[x]+max(0,rm[son[x][0]]));
    }
     
    void covered(int x,int v)
    {
        val[x]=v;
        sum[x]=siz[x]*v;
        lm[x]=rm[x]=max(0,sum[x]);
        ma[x]=max(sum[x],val[x]);
        cov[x]=v;
    }
     
    void zhuan(int now)
    {
        swap(son[now][0],son[now][1]);
        swap(lm[now],rm[now]);
        mark[now]^=1;
    }
     
    void pd(int now)
    {
        if(mark[now]){
            if(son[now][0])zhuan(son[now][0]);
            if(son[now][1])zhuan(son[now][1]);
        }
        if(cov[now]!=inf){
            if(son[now][0])covered(son[now][0],cov[now]);
            if(son[now][1])covered(son[now][1],cov[now]);
        }
        mark[now]=0;cov[now]=inf;
    }
     
    int build(int l,int r)
    {
        if(l>r)return 0;
        int mid=(l+r)>>1,v=a[mid];
        int now=newnode(v);
        son[now][0]=build(l,mid-1);
        son[now][1]=build(mid+1,r);
        upda(now);
        return now;
    }
     
    void dfs(int now)
    {
        if(!now)return;
        dfs(son[now][0]);
        printf("%d ",val[now]);
        dfs(son[now][1]);
    }
     
    void spli(int now,int k,int &x,int &y)
    {
        if(!now)x=y=0;
        else{
            pd(now);
            if(k<=siz[son[now][0]])
                y=now,spli(son[now][0],k,x,son[now][0]);
            else
                x=now,spli(son[now][1],k-siz[son[now][0]]-1,son[now][1],y);
            upda(now);
        }
    }
     
    int merge(int x,int y)
    {
        if(!x||!y)return x+y;
        pd(x),pd(y);
        if(pri[x]<pri[y])
        {
            son[x][1]=merge(son[x][1],y);
            upda(x);
            return x;
        }else{
            son[y][0]=merge(x,son[y][0]);
            upda(y);
            return y;
        }
    }
     
    void rudui(int x)
    {
        if(!x)return ;
        q.push(x);
        rudui(son[x][0]);
        rudui(son[x][1]);
    }
     
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i)scanf("%d",&a[i]);
        sum[0]=siz[0]=mark[0]=cov[0]=0;
        ma[0]=val[0]=-inf;
        rt=build(1,n);
        int pos,num,x,y,z,k,b,c,d;
        for(int i=1;i<=m;++i)
        {
            //dfs(rt);printf("
    "); 
            scanf("%s",ch+1);
            if (ch[1]=='I'){
                scanf("%d %d",&pos,&num);
                for(int i=1;i<=num;++i)scanf("%d",&a[i]);
                z=build(1,num);
                spli(rt,pos,x,y);
                rt=merge(merge(x,z),y);
            }else if (ch[1]=='D'){
                scanf("%d%d",&pos,&num);
                spli(rt,pos-1,x,y);
                spli(y,num,b,c);
                rt=merge(x,c);
                rudui(b);//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            }else if (ch[1]=='M' && ch[3] =='K'){
                scanf("%d%d%d",&pos,&num,&k);
                spli(rt,pos-1,x,y);
                spli(y,num,b,c);
                covered(b,k);
                rt=merge(x,merge(b,c));
            }else if (ch[1]=='R'){
                scanf("%d%d",&pos,&num);
                spli(rt,pos-1,x,y);
                spli(y,num,b,c);
                zhuan(b);
                rt=merge(x,merge(b,c));
            }else if (ch[1]=='G'){
                scanf("%d%d",&pos,&num);
                spli(rt,pos-1,x,y);
                spli(y,num,b,c);
                printf("%d
    ",sum[b]);
                rt=merge(x,merge(b,c));
            }else{
                printf("%d
    ",ma[rt]);
            }
        }
        return 0;
    }
  • 相关阅读:
    sql执行的顺序
    $(obj).index(this) 与 $(this).index()的区别
    java取得百分比
    取得input的特殊值
    清除select的边框和三角形
    在jsp页面中获取列表长度
    mysql mybatis 批量更新和新增
    oracle mybatis 批量更新和新增
    jstl if else 判断
    判断radio,select,checkbox是否选中的方法
  • 原文地址:https://www.cnblogs.com/rir1715/p/7880819.html
Copyright © 2011-2022 走看看