bzoj1251 序列終結者

Description

網上有許多題,就是給定一個序列,要你支持幾種操作:A、B、C、D。一看另一道題,又是一個序列 要支持幾種操作:D、C、B、A。尤其是我們這裏的某人,出模擬試題,居然還出了一道這樣的,真是沒技術含量……這樣 我也出一道題,我出這一道的目的是爲了讓大家以後做這種題目有一個“庫”可以依靠,沒有什麼其他的意思。這道題目 就叫序列終結者吧。 【問題描述】 給定一個長度爲N的序列,每個序列的元素是一個整數(廢話)。要支持以下三種操作: 1. 將[L,R]這個區間內的所有數加上V。 2. 將[L,R]這個區間翻轉,比如1 2 3 4變成4 3 2 1。 3. 求[L,R]這個區間中的最大值。 最開始所有元素都是0。

Input

第一行兩個整數N,M。M爲操作個數。 以下M行,每行最多四個整數,依次爲K,L,R,V。K表示是第幾種操作,如果不是第1種操作則K後面只有兩個數。

Output

對於每個第3種操作,給出正確的回答。

Sample Input

4 4
1 1 3 2
1 2 4 -1
2 1 3
3 2 4

Sample Output

2
【數據範圍】
N<=50000,M<=100000。

HINT

splay模板題

#include <stdio.h>
#include <algorithm>
using namespace std;
const int maxn=50007;
int id[maxn],root;
int rev[maxn];
int tr[maxn][2];
int mx[maxn];
int sum[maxn];
int size[maxn];
int val[maxn];
int fa[maxn];
void pushup(int k){
    int l=tr[k][0],r=tr[k][1];
    mx[k]=max(mx[l],mx[r]);
    mx[k]=max(mx[k],val[k]);
    size[k]=size[l]+size[r]+1;
}
void rotate(int x,int &k){
    int y=fa[x],z=fa[y];
    int l,r;
    if(y!=k){
        if(tr[z][0]==y) tr[z][0]=x;
        else tr[z][1]=x;
    }
    else k=x;
    if(tr[y][0]==x) l=0;
    else l=1;
    r=l^1;
    fa[x]=z;
    fa[y]=x;
    tr[y][l]=tr[x][r];
    fa[tr[x][r]]=y;
    tr[x][r]=y;
    pushup(y);
    pushup(x);
}
void splay(int x,int &k){
    int y,z;
    while(x!=k){
        y=fa[x],z=fa[y];
        if(y!=k){
            if(tr[z][0]==y^tr[y][0]==x) rotate(x,k);
            else rotate(y,k);
        }
        rotate(x,k);
    }
}
void pushdown(int k){
    int l=tr[k][0],r=tr[k][1];
    if(rev[k])
    {
        rev[k]=0;
        l=tr[k][0];r=tr[k][1];
        rev[l]^=1;rev[r]^=1;
        swap(tr[k][0],tr[k][1]);
    }
    if(sum[k])
    {
        int t=sum[k];
        if(l){
            sum[l]+=t;val[l]+=t;mx[l]+=t;
        }
        if(r){
            sum[r]+=t;val[r]+=t;mx[r]+=t;
        }
        sum[k]=0;
    }
}
void build(int l,int r,int f)
{
    if(l>r) return;
    int now=id[l],last=id[f];
    if(l==r)
    {
        fa[now]=last;
        val[now]=0;
        if(l<f) tr[last][0]=now;
        else tr[last][1]=now;
        size[now]=1;
        return;
    }
    int mid=(l+r)>>1;
    now=id[mid];
    build(l,mid-1,mid);
    build(mid+1,r,mid);
    pushup(now);
    fa[now]=last;
    if(mid>f) tr[last][1]=now;
    else tr[last][0]=now;
}
int query_num(int k,int rank){
    pushdown(k);
    if(k==0) return 0;
    if(size[tr[k][0]]>=rank)
    return query_num(tr[k][0],rank);
    else if(rank>size[tr[k][0]]+1)
    return query_num(tr[k][1],rank-size[tr[k][0]]-1);
    else return k;
}
int rever(int x,int y){
    x=query_num(root,x);
    y=query_num(root,y+2);
    splay(x,root);
    splay(y,tr[x][1]);
    rev[tr[y][0]]^=1;
}
int zz(int x,int y,int c){
    x=query_num(root,x);
    y=query_num(root,y+2);
    splay(x,root);
    splay(y,tr[x][1]);
    sum[tr[y][0]]+=c;
    mx[tr[y][0]]+=c;
    val[tr[y][0]]+=c;
}
int query(int x,int y){
    x=query_num(root,x);
    y=query_num(root,y+2);
    splay(x,root);
    splay(y,tr[x][1]);
    return mx[tr[y][0]];
}
int main(){
    mx[0]=-99999999;
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n+2;i++)
    id[i]=i;
    build(1,n+2,0);
    root=(n+3)>>1;
    for(int i=1;i<=m;i++){
        int a;
        scanf("%d",&a);
        if(a==1){
            int b,c,d;
            scanf("%d%d%d",&b,&c,&d);
            zz(b,c,d);
        }
        else if(a==2)
        {
            int b,c;
            scanf("%d%d",&b,&c);
            rever(b,c);
        }
        else{
            int b,c;
            scanf("%d%d",&b,&c);
            printf("%d\n",query(b,c));
        }
    }
    return 0;
}

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