题意:有一个序列\(a_n\)和若干操作:
- \(\mathrm{1\ l \ r \ }\) 求\(a_l\)到\(a_r\)的和
- \(\mathrm{2\ l \ r \ val \ }\) 将\(a_l\)到\(a_r\)赋值为\(\mathrm{val}\)
- \(\mathrm{3\ l \ r \ val\ }\)将\(a_l\)到\(a_r\)加上\(\mathrm{val}\)
- \(\mathrm{4\ l_1 \ r_1 \ l_2 \ r_2 }\)将\(a_{l_1}\)到\(a_{r_1}\)复制到\(a_{l_2}\)到\(a_{r_2}\)处
- \(\mathrm{5\ l_1 \ r_1 \ l_2 \ r_2 }\)将\(a_{l_1}\)到\(a_{r_1}\)与\(a_{l_2}\)到\(a_{r_2}\)交换
- \(\mathrm{6\ l \ r \ }\)将\(a_l\)到\(a_r\)翻转
分析:额,有区间赋值操作,那就上珂朵莉吧.操作一,二,三都是珂朵莉的常规操作,不讲了.
对于操作四,开一个vector,把\([l1,r1]\)放进vector,然后把\([l2,r2]erase\)掉,再把\(vector\)里的\(insert\)到\([l2,r2]\)中;
对于操作五,开两个\(vector\),像上面一样操作即可.
对于操作六,还是一个\(vector\),把\([l,r]\)放进vector,然后把\([l,r]erase\)掉,再把\(vector\)里的\(insert\)到\([r,l]\)中.注意是\([r,l]\).
因为STL常数较大,要吸氧才能光速逃跑...
// luogu-judger-enable-o2
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define IT set<node>::iterator
#define It vector<node>::iterator
using namespace std;
inline int read(){
int x=0,o=1;char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')o=-1,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*o;
}
const int mod=1e9+7;
struct node{
int l,r;mutable int val;
node(int L,int R=-1,int V=0){l=L,r=R,val=V;}
bool operator <(const node &x)const{
return l<x.l;
}
};
set<node>s;
inline IT split(int pos){
IT it=s.lower_bound(node(pos));
if(it!=s.end()&&it->l==pos)return it;
--it;int l=it->l,r=it->r,val=it->val;
s.erase(it);s.insert(node(l,pos-1,val));
return s.insert(node(pos,r,val)).first;
}
inline int ask_sum(int l,int r){
int val=0;IT itr=split(r+1),itl=split(l);
for(;itl!=itr;++itl)
val=(val+1ll*itl->val*(itl->r-itl->l+1)%mod)%mod;
return val;
}
inline void assign(int l,int r,int val){
IT itr=split(r+1),itl=split(l);
s.erase(itl,itr);s.insert(node(l,r,val));
}
inline void add(int l,int r,int val){
IT itr=split(r+1),itl=split(l);
for(;itl!=itr;++itl)itl->val=(itl->val+val)%mod;
}
inline void change1(int l1,int r1,int l2,int r2){
vector<node>q;q.clear();
for(IT itr=split(r1+1),itl=split(l1);itl!=itr;++itl)q.push_back(*itl);
IT itr=split(r2+1),itl=split(l2);s.erase(itl,itr);
for(It i=q.begin();i!=q.end();++i)s.insert(node(i->l-l1+l2,i->r-l1+l2,i->val));
}
inline void change2(int l1,int r1,int l2,int r2){
if(l1>l2)swap(l1,l2),swap(r1,r2);
vector<node>q1,q2;q1.clear(),q2.clear();
for(IT itr=split(r1+1),itl=split(l1);itl!=itr;++itl)q1.push_back(*itl);
for(IT itr=split(r2+1),itl=split(l2);itl!=itr;++itl)q2.push_back(*itl);
IT itr=split(r1+1),itl=split(l1);s.erase(itl,itr);
itr=split(r2+1),itl=split(l2);s.erase(itl,itr);
for(It i=q1.begin();i!=q1.end();++i)s.insert(node(i->l-l1+l2,i->r-l1+l2,i->val));
for(It i=q2.begin();i!=q2.end();++i)s.insert(node(i->l-l2+l1,i->r-l2+l1,i->val));
}
inline void Reverse(int l,int r){
vector<node>q;q.clear();
for(IT itr=split(r+1),itl=split(l);itl!=itr;++itl)q.push_back(*itl);
IT itr=split(r+1),itl=split(l);s.erase(itl,itr);
for(It i=q.begin();i!=q.end();++i)s.insert(node(r-i->r+l,r-i->l+l,i->val));
}
int main(){
int n=read(),m=read();
for(int i=1;i<=n;++i){
int a=read();
s.insert(node(i,i,a));
}
while(m--){
int opt=read(),l=read(),r=read();
if(opt==1){printf("%d\n",ask_sum(l,r)%mod);continue;}
if(opt==2){int val=read();assign(l,r,val);continue;}
if(opt==3){int val=read();add(l,r,val);continue;}
if(opt==4){int l2=read(),r2=read();change1(l,r,l2,r2);continue;}
if(opt==5){int l2=read(),r2=read();change2(l,r,l2,r2);continue;}
if(opt==6){Reverse(l,r);continue;}
}
for(IT it=s.begin();it!=s.end();++it)
for(int i=it->l;i<=it->r;i++)
printf("%d ",it->val%mod);
printf("\n");
return 0;
}