天天看點

[NOI2005]維修數列(Splay神題)

我這個題22次失敗送出(WA & TLE & MLE & RE),然後才AC了。。。

這個題真的把Splay當成了線段樹來用,打了好多标記,還一直pushup&&pushdown

其實所有操作都差不多,隻是打的标記不同罷了。

比如我們要操作[L,R],那麼就将L-1 Splay到根,将R+1 Splay到根的右兒子,這樣就可以操作了(自己腦補一下)

然後這個題有一個坑點,就是最大子段和必須選,也就是說,如果全是負數,還是必須選一個,不能輸出零。

其實這個題就是操作太多,才不好調,每個操作單獨拉出來都不難。

代碼:(跑得還挺快 https://www.luogu.org/record/show?rid=4147310)

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#define ll long long
using namespace std;
inline int read(){
    int x=;char ch=' ';int f=;
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')f=-,ch=getchar();
    while(ch>='0'&&ch<='9')x=(x<<)+(x<<)+(ch^),ch=getchar();
    return x*f;
}
const int N=+;
const int inf=+;
int n,m,sz,root;
int key[N],ch[N][],sum[N],mx[N],lx[N],rx[N],rev[N],cg[N],size[N],f[N];
int s[N],top;
inline int New(){return top?s[top--]:++sz;}
inline void pre(int x,int v){
    ch[x][]=ch[x][]=f[x]=cg[x]=rev[x]=;
    size[x]=;key[x]=sum[x]=mx[x]=lx[x]=rx[x]=v;
}
inline void cover(int x,int v){
    cg[x]=;sum[x]=v*size[x];
    key[x]=v;mx[x]=lx[x]=rx[x]=max(key[x],sum[x]);
    rev[x]=;
}
inline void rever(int x){
    if(cg[x])return;
    rev[x]^=;
    swap(ch[x][],ch[x][]);swap(lx[x],rx[x]);
}
inline void update(int x){
    int l=ch[x][],r=ch[x][];
    sum[x]=sum[l]+sum[r]+key[x];
    lx[x]=max(lx[l],sum[l]+key[x]+max(lx[r],));
    rx[x]=max(rx[r],sum[r]+key[x]+max(rx[l],));
    mx[x]=max(max(mx[l],mx[r]),max(,lx[r])+max(,rx[l])+key[x]);
    size[x]=size[l]+size[r]+;
}
inline void pushdown(int x){
    int l=ch[x][],r=ch[x][];
    if(rev[x]){
        if(l)rever(l);
        if(r)rever(r);
        rev[x]=;
    }
    if(cg[x]){
        if(l)cover(l,key[x]);
        if(r)cover(r,key[x]);
        cg[x]=;
    }
}
inline bool get(int x){return ch[f[x]][]==x;}
inline void clear(int x){ch[x][]=ch[x][]=f[x]=size[x]=sum[x]=key[x]=lx[x]=rx[x]=mx[x]=rev[x]=cg[x]=;}
inline void rotate(int x){
    int y=f[x],z=f[y],w=get(x),w2=get(y);
    ch[y][w]=ch[x][w^];f[ch[y][w]]=y;
    ch[x][w^]=y;f[y]=x;
    f[x]=z;if(z)ch[z][w2]=x;
    update(y);update(x);
}
inline void splay(int x,int goal){
    for(int fa=;(fa=f[x])!=goal;rotate(x))
        if(f[fa]!=goal)
            rotate((get(x)==get(fa))?fa:x);
    if(!goal)root=x;
}
inline int kth(int k){
    int now=root;
    while(){
        pushdown(now);
        if(k<=size[ch[now][]])now=ch[now][];
        else{
            if(k<=size[ch[now][]]+){return now;}
            k-=size[ch[now][]]+;now=ch[now][];
        }
    }
}
int v[N];
inline void build(int &x,int l,int r,int fa){
    if(l>r){x=;return;}
    int mid=(l+r)>>;
    x=New();pre(x,v[mid]);f[x]=fa;
    if(l==r)return;
    build(ch[x][],l,mid-,x);
    build(ch[x][],mid+,r,x);
    update(x);
}
inline void insert(){
    int x=read();int tot=read();if(!tot)return;
    for(int i=;i<=tot;i++)v[i]=read();
    int l=kth(x+);splay(l,);
    int r=kth(x+);splay(r,l);
    build(ch[r][],,tot,r);
    update(r);update(l);
}
inline void recycle(int x){
    if(!x)return;
    s[++top]=x;
    recycle(ch[x][]);recycle(ch[x][]);
}
inline void del(){
    int x=read();int tot=read();if(!tot)return;
    int l=kth(x);splay(l,);
    int r=kth(x+tot+);splay(r,l);
    recycle(ch[r][]);ch[r][]=;
    update(r);update(l);
}
inline void modify(){
    int x=read();int tot=read();int c=read();if(!tot)return;
    int l=kth(x);splay(l,);
    int r=kth(x+tot+);splay(r,l);
    cover(ch[r][],c);
    update(r);update(l);
}
inline void reverse(){
    int x=read();int tot=read();if(!tot)return;
    int l=kth(x);splay(l,);
    int r=kth(x+tot+);splay(r,l);
    rever(ch[r][]);
    update(r);update(l);
}
inline void query_sum(){
    int x=read();int tot=read();if(!tot){printf("0\n");return;}
    int l=kth(x);splay(l,);
    int r=kth(x+tot+);splay(r,l);
    printf("%d\n",sum[ch[r][]]);
}
inline void query_mx(){
    printf("%d\n",mx[root]);
}
inline void print(int x){
    if(ch[x][])print(ch[x][]);
    cout<<"data of "<<x<<":"<<endl;
    cout<<"key["<<x<<"]="<<key[x]<<' ';
    cout<<"size["<<x<<"]="<<size[x]<<endl;
    cout<<"ls["<<x<<"]="<<ch[x][]<<' ';
    cout<<"rs["<<x<<"]="<<ch[x][]<<' ';
    cout<<"sum["<<x<<"]="<<sum[x]<<endl;
    cout<<"lx["<<x<<"]="<<lx[x]<<' ';
    cout<<"rx["<<x<<"]="<<rx[x]<<' ';
    cout<<"mx["<<x<<"]="<<mx[x]<<endl;
    cout<<"fa["<<x<<"]="<<f[x]<<' ';
    cout<<"cg["<<x<<"]="<<cg[x]<<' ';
    cout<<"rev["<<x<<"]="<<rev[x]<<endl;
    cout<<"end data."<<endl;
    cout<<endl;
    if(ch[x][])print(ch[x][]);
}
int main(){
    // freopen("test.out","w",stdout);
    n=read();m=read();
    mx[]=v[]=v[n+]=-inf;
    // mx[0]=-inf;
    for(int i=;i<=n+;i++)v[i]=read();
    build(root,,n+,);
    // int _1=kth(1);int _n=kth(n+2);
    // mx[_1]=-inf;mx[_n]=-inf;
    char ch[];
    while(m--){
        scanf("%s",ch);
        // printf("%s\n",ch);
        if(ch[]=='S')insert();
        else if(ch[]=='L')del();
        else if(ch[]=='K')modify();
        else if(ch[]=='V')reverse();
        else if(ch[]=='T')query_sum();
        else query_mx();
        // print(root);
        // cout<<endl<<endl<<endl<<endl<<endl;
    }
    return ;
}