[LG-P5350]序列

必要的前置知识: [CF876C]Willem, Chtholly and Seniorious(ODT)

操作\(1,2,3\)就是原题。。不讲了。。

操作\(4,5,6\)

把ODT的set中的那一段点存入一个vector,然后把两边的左右端点换一下,在插入就好了。。

只不过在操作时要时刻注意ODT的先右后左原则。。


\(O_2\)才能过。。喔太菜了。。

#include<bits/stdc++.h>
using namespace std;

const int MOD=1e9+7;

int n,m;

struct node{
    int l,r;
    mutable int v;
    node(int l,int r=-1,int v=0):l(l),r(r),v(v){}
    bool operator <(const node &b)const {return l<b.l;}
};

typedef set<node>::iterator iter;

set<node>s;

inline iter split(int pos){
    iter it=s.lower_bound(node(pos));
    if(it!=s.end()&&it->l==pos)return it;
    int l=(--it)->l,r=it->r,v=it->v;
    s.erase(it),s.insert(node(l,pos-1,v));
    return s.insert(node(pos,r,v)).first;
}

inline void add(int l,int r,int val){
    iter itr=split(r+1),itl=split(l);
    for(;itl!=itr;++itl)itl->v=(itl->v+val)%MOD;
}

inline void assign_val(int l,int r,int val){
    iter itr=split(r+1),itl=split(l);
    s.erase(itl,itr),s.insert(node(l,r,val));
}

inline int sum(int l,int r){
    iter itr=split(r+1),itl=split(l);
    int ret=0;
    for(iter it=itl;it!=itr;it++) ret=(ret+1ll*(it->r-it->l+1)*it->v%MOD)%MOD;
    return ret;
}

inline void copy(int a,int b,int c,int d){
    iter ita,itb,itc,itd;
    if(a>c) itb=split(b+1),ita=split(a),itd=split(d+1),itc=split(c);
    else itd=split(d+1),itc=split(c),itb=split(b+1),ita=split(a);
    vector<node> tmp;
    for(iter it=ita;it!=itb;++it){
        node ls=*it;
        ls.l+=c-a,ls.r+=c-a,
        tmp.push_back(ls);
    }
    s.erase(itc,itd);
    for(vector<node>::iterator it=tmp.begin();it!=tmp.end();++it) s.insert(*it);
}

inline void swap(int a,int b,int c,int d){
    iter ita,itb,itc,itd;
    if(a>c) itb=split(b+1),ita=split(a),itd=split(d+1),itc=split(c);
    else itd=split(d+1),itc=split(c),itb=split(b+1),ita=split(a);
    vector<node> tmp;
    for(iter it=ita;it!=itb;++it){
        node ls=*it;
        ls.l+=c-a,ls.r+=c-a,
        tmp.push_back(ls);
    }
    for(iter it=itc;it!=itd;++it){
        node ls=*it;
        ls.l-=c-a,ls.r-=c-a,
        tmp.push_back(ls);
    }
    s.erase(itc,itd),
    ita=s.lower_bound(node(a)),itb=s.lower_bound(node(b+1)),
    s.erase(ita,itb);
    for(vector<node>::iterator it=tmp.begin();it!=tmp.end();++it) s.insert(*it);
}
inline void reverse(int l,int r){
    iter itr=split(r+1),itl=split(l);
    vector<node> tmp;
    for(iter it=itl;it!=itr;it++) tmp.push_back(*it);
    s.erase(itl,itr);
    for(int i=tmp.size()-1,now=0;~i;--i){
        int sz=tmp[i].r-tmp[i].l+1;
        tmp[i].l=l+now,tmp[i].r=l+now+sz-1,
        now+=sz,
        s.insert(tmp[i]);
    }
}

int main(){
    scanf("%d%d",&n,&m);
    for(int i=1,t;i<=n;++i)
        scanf("%d",&t),
        s.insert(node(i,i,t));
    s.insert(node(n+1,n+1,0));
    while(m--){
        int op,x,y,z,t;
        scanf("%d",&op);
        if(op==1)
            scanf("%d%d",&x,&y),
            printf("%d\n",sum(x,y));
        else if(op==2)
            scanf("%d%d%d",&x,&y,&z),
            assign_val(x,y,z);
        else if(op==3)
            scanf("%d%d%d",&x,&y,&z),
            add(x,y,z);
        else if(op==4)
            scanf("%d%d%d%d",&x,&y,&z,&t),
            copy(x,y,z,t);
        else if(op==5)
            scanf("%d%d%d%d",&x,&y,&z,&t),
            swap(x,y,z,t);
        else
            scanf("%d%d",&x,&y),
            reverse(x,y);
    }
    for(iter it=s.begin();it!=s.end();++it){
        if(it->l==n+1) break;
        for(int i=1;i<=it->r-it->l+1;++i) printf("%d ",it->v);
    }
    return 0;
}
posted @ 2019-06-02 14:14  蒟蒻SLS  阅读(140)  评论(0编辑  收藏  举报