【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("\n"); 
        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\n",sum[b]);
            rt=merge(x,merge(b,c));
        }else{
            printf("%d\n",ma[rt]);
        }
    }
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM