[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;
}