【BZOJ】1251 序列終結者 Splay

題目傳送門

這題其實就是一道Splay的區間修改模板題,太棒啦,又水了一篇blog!

其實Splay的區間加上一個值用的就是線段樹的延遲標記的思想,實現就和下放區間反轉的標記一樣。區間求最大值也是類似的。

於是這題就是練一下碼力的水題。

附上AC代碼:

#include <cstdio>
#include <cctype>
#include <algorithm>
using namespace std;

const int N=5e4+10;
int n,m,mx[N],rt,f[N],sz[N],ch[N][2],w[N],o,x,y,v,tag[N],rev[N];

inline char nc(void){
    static char ch[100010],*p1=ch,*p2=ch;
    return p1==p2&&(p2=(p1=ch)+fread(ch,1,100010,stdin),p1==p2)?EOF:*p1++;
}

inline void read(int &a){
    static char c=nc();int f=1;
    for (;!isdigit(c);c=nc()) if (c=='-') f=-1;
    for (a=0;isdigit(c);a=(a<<3)+(a<<1)+c-'0',c=nc());
    return (void)(a*=f);
}

inline void updata(int k){return (void)(mx[k]=max(max(mx[ch[k][0]],mx[ch[k][1]]),w[k]),sz[k]=sz[ch[k][0]]+sz[ch[k][1]]+1);}

inline void rotate(int x){
    int y=f[x],op=(ch[y][1]==x);
    ch[y][op]=ch[x][op^1];
    if (ch[x][op^1]) f[ch[x][op^1]]=y;
    f[x]=f[y];
    if (f[y]) ch[f[y]][ch[f[y]][1]==y]=x;
    f[y]=x,ch[x][op^1]=y;
    return updata(y),updata(x);
}

inline void splay(int x,int ed){
    for (int fa=f[x]; fa!=ed; rotate(x),fa=f[x])
        if (f[fa]!=ed) rotate((ch[fa][0]==x)==(ch[f[fa]][0]==fa)?fa:x);
    if (!ed) rt=x;
    return;
}

inline void build(int l,int r,int pre){
    if (l>r) return;
    if (l==r) return (void)(f[l]=pre,sz[l]=1,ch[pre][l>pre]=l);
    int mid=l+r>>1;
    build(l,mid-1,mid),build(mid+1,r,mid);
    return (void)(f[mid]=pre,updata(mid),ch[pre][mid>pre]=mid);
}

inline void push(int k){
    if (tag[k]){
        if (ch[k][0]) tag[ch[k][0]]+=tag[k],mx[ch[k][0]]+=tag[k],w[ch[k][0]]+=tag[k];
        if (ch[k][1]) tag[ch[k][1]]+=tag[k],mx[ch[k][1]]+=tag[k],w[ch[k][1]]+=tag[k];
        tag[k]=0;
    }
    if (rev[k]) rev[ch[k][0]]^=1,rev[ch[k][1]]^=1,rev[k]=0,swap(ch[k][0],ch[k][1]);
}

inline int find(int k,int rk){
    if (tag[k]||rev[k]) push(k);
    if (sz[ch[k][0]]>=rk) return find(ch[k][0],rk);
    if (sz[ch[k][0]]+1==rk) return k;
    return find(ch[k][1],rk-sz[ch[k][0]]-1);
}

inline void add(int x,int y,int v){
    int l=find(rt,x),r=find(rt,y+2);
    splay(l,0),splay(r,rt);
    int k=ch[r][0];
    return (void)(tag[k]+=v,mx[k]+=v,w[k]+=v);
}

inline void flip(int x,int y){
    int l=find(rt,x),r=find(rt,y+2);
    return (void)(splay(l,0),splay(r,rt),rev[ch[r][0]]^=1);
}

inline void query(int x,int y){
    int l=find(rt,x),r=find(rt,y+2);
    splay(l,0),splay(r,rt);
    printf("%d\n",mx[ch[r][0]]);
}

int main(void){
    read(n),read(m),mx[0]=-2e9,build(1,n+2,0),rt=(n+3)>>1;
    while (m--){
        read(o),read(x),read(y);
        switch (o){
            case 1: read(v),add(x,y,v);break;
            case 2: flip(x,y);break;
            case 3: query(x,y);break;
        }
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章