zoukankan      html  css  js  c++  java
  • 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;
    }
    
    
  • 相关阅读:
    Spring.Net框架与WCF的集成(上)
    重入与回调并发(Reentrant & CallbackConcurrency )
    WCF中的异步实现
    WCF开发时如何选择正确的实例模式(InstanceMode)?
    WCF实例与并发
    WCF消息可靠性与有序传递
    WCF实际应用之IParameterInspector扩展
    WCF中几个基本知识点整理
    HTTP与Tcp协议下双工通信的差异
    细说WCF中的会话模式
  • 原文地址:https://www.cnblogs.com/JohnRan/p/12885322.html
Copyright © 2011-2022 走看看