luogu P2042

Posted johnran

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu P2042相关的知识,希望对你有一定的参考价值。

luogu P2042

主要是贴一下维护序列的板子:

#include<bits/stdc++.h>

using namespace std;

const int N = 1000005;
const int inf = 1e8+1;
const int NONE = 1e9;

#define ls(x) (bst[x].ch[0])
#define rs(x) (bst[x].ch[1])
#define getKey(x) (bst[x].key)
#define getSize(x) (bst[x].sz)
#define getFather(x) (bst[x].f)

struct splayNode{
    int ch[2];
    int f;
    int sz;
    int key;
    int tag;
    int rev;
    int sum;
    int left;
    int right;
    int middle;
    void clear(){ch[0]=ch[1]=f=rev=0;tag=NONE;}
}bst[N];

inline bool getDir(int x){return rs(getFather(x))==x;}

int rt, cntNode, top, a[N], id[N], rub[N], n, m;

inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}

int getId(){//防止节点过多,我们需要设置一个垃圾堆,有废弃的节点应该优先使用
    if(top==0)return ++cntNode;
    return rub[top--];
}

void changeVal(int nd, int val){
    if(!nd)return;
    bst[nd].tag=bst[nd].key=val;
    bst[nd].sum=val*getSize(nd);
    bst[nd].left=bst[nd].right=max(bst[nd].sum,0);
    bst[nd].middle=max(bst[nd].sum,val);
}

void changeRev(int nd){
    swap(ls(nd),rs(nd));
    swap(bst[nd].left,bst[nd].right);
    bst[nd].rev^=1;
}

void pushup(int nd){
    splayNode& x=bst[bst[nd].ch[0]], &y=bst[bst[nd].ch[1]];
    splayNode& res=bst[nd];
    int val=bst[nd].key;

    res.sum=x.sum+y.sum+val;
    res.sz=x.sz+y.sz+1;
    res.middle=max(max(x.middle,y.middle),x.right+y.left+val);
    res.left=max(x.left,x.sum+val+y.left);
    res.right=max(y.right,y.sum+val+x.right);
    //cout<<"pushup: "<<nd<<" "<<res.sum<<" "<<res.left<<" "<<res.right<<endl;
}

void pushdown(int nd){
    if(bst[nd].tag!=NONE){//赋值标记
        changeVal(ls(nd),bst[nd].tag);
        changeVal(rs(nd),bst[nd].tag);
        bst[nd].tag=NONE;
    }

    if(bst[nd].rev){
        changeRev(ls(nd));
        changeRev(rs(nd));
        bst[nd].rev=0;
    }
}

void rot(int nd){
    int fa=getFather(nd),gf=getFather(fa);
    int ws=getDir(nd),ws1=getDir(fa);

    int nd1=bst[nd].ch[ws^1];

    bst[fa].ch[ws]=nd1;bst[nd1].f=fa;
    bst[gf].ch[ws1]=nd;bst[nd].f=gf;
    bst[nd].ch[ws^1]=fa;bst[fa].f=nd;
    pushup(fa);pushup(nd);
}

void splay(int nd, int goal=0){
    while(getFather(nd)!=goal){
        int fa=getFather(nd);
        int gf=getFather(fa);
        if(gf!=goal){
            if(getDir(nd)==getDir(fa))rot(fa);
            else rot(nd);
        }

        rot(nd);
    }
    if(!goal)rt=nd;
}

int kth(int k){
    int nd=rt;
    while(1){
        pushdown(nd);
        if(getSize(ls(nd))>=k)nd=ls(nd);
        else if(k==getSize(ls(nd))+1)return nd;
        else{
            k-=getSize(ls(nd))+1;
            nd=rs(nd);
        }
    }
}

int split(int s, int len){//拆出响应的区间
    int x=kth(s),y=kth(s+len+1);
    splay(x,0);splay(y,x);

    return ls(y);
}

void newNode(int nd, int x){//newc出一新节点
    bst[nd].middle=bst[nd].sum=x;
    bst[nd].tag=NONE;bst[nd].rev=0;
    bst[nd].left=bst[nd].right=max(x,0);
    bst[nd].sz=1;
}

void build(int s, int e, int fa){
    int mid=(s+e)>>1;int curNode=id[mid],pre=id[fa];
    if(s==e){
        newNode(curNode,a[s]);
    }

    if(s<mid)build(s,mid-1,mid);
    if(mid<e)build(mid+1,e,mid);
    bst[curNode].key=a[mid];bst[curNode].f=pre;bst[curNode].tag=NONE;
    pushup(curNode);
    bst[pre].ch[mid>=fa]=curNode;
}

void Insert(int s, int len){//先建树,再插入
    for(int i=1;i<=len;++i)a[i]=read();
    for(int i=1;i<=len;++i)id[i]=getId();

    build(1,len,0);
    int z=id[(1+len)>>1];
    int x=kth(s+1),y=kth(s+2);
    splay(x,0);splay(y,x);
    getFather(z)=y;ls(y)=z;
    pushup(y);pushup(x);
}

void removeTree(int nd){
    if(ls(nd))removeTree(ls(nd));
    if(rs(nd))removeTree(rs(nd));
    rub[++top]=nd;bst[nd].clear();
}

void del(int x, int len){
    int nd=split(x,len);int y=getFather(nd);
    removeTree(nd),ls(y)=0;
    pushup(y);pushup(getFather(y));
}

void update(int x, int len, int val){
    int nd=split(x,len),y=getFather(nd);
    changeVal(nd,val);
    pushup(y),pushup(getFather(y));
}

void reverseTree(int x, int len){
    int nd=split(x,len),y=getFather(nd);
    if(bst[nd].tag!=NONE)return;//区间被整体赋值了
    changeRev(nd);
    pushup(y);pushup(getFather(y));
}

int query(int x, int len){//求和
    int nd=split(x,len);
    return bst[nd].sum;
}

int main(){
    n=read(),m=read();
    bst[0].middle=a[1]=a[n+2]=-inf;


    for(int i=2;i<=n+1;++i)a[i]=read();
    for(int i=1;i<=n+2;++i)id[i]=i;
    build(1,n+2,0);

    rt=(n+3)>>1;cntNode=n+2;

    char s[25];
    int opt,start,num,val;
    for(int i=1;i<=m;++i){
        scanf("%s",s+1);
        if(s[1]==‘I‘){
            start=read();num=read();
            Insert(start,num);
        }else if(s[1]==‘D‘){
            start=read();num=read();
            del(start,num);
        }else if(s[1]==‘M‘&&s[3]==‘K‘){
            start=read();num=read();val=read();
            update(start,num,val);
        }else if(s[1]==‘M‘&&s[3]==‘X‘){
           cout<<bst[rt].middle<<endl;
        }else if(s[1]==‘R‘){
            start=read(),num=read();
            reverseTree(start,num);
        }else{
            start=read();num=read();
            cout<<query(start,num)<<endl;
        }
    }

    return 0;
}

以上是关于luogu P2042的主要内容,如果未能解决你的问题,请参考以下文章

洛谷 P2042 维护数列

p2042 维修数列(SPLAY)

微信小程序代码片段

VSCode自定义代码片段——CSS选择器

谷歌浏览器调试jsp 引入代码片段,如何调试代码片段中的js

片段和活动之间的核心区别是啥?哪些代码可以写成片段?