题解:序列
ODT 珂朵莉树
如果你不会,你可以看看:ODT 珂朵莉树。
数据随机,且有区间赋值,因此考虑 ODT。
操作 \(1\sim3\) 是简单的,考虑操作 \(4\sim6\)。
操作 \(4\):区间复制
区间不交,分别 split 操作后,暴力记录 \([l_1,r_1]\) 的信息,删除 \([l_2,r_2]\) 的信息再插入记录信息即可。
同时注意区间端点需要偏移,偏移量为 \(l_2-l_1=r_2-r_1\)。
操作 \(5\):区间交换
区间交换,可以分别记录两个区间的信息,删除原信息后插入即可。
同时注意端点需要偏移,偏移量为 \(\pm(l_2-l_1)=\pm(r_2-r_1)\)。
操作 \(6\):区间翻转
在区间 \([l,r]\) 内有多个区间 \([l_1,r_1],[l_2,r_2],\cdots,[l_k,r_k]\),需要翻转。
发现翻转得到的 \([l_i',r_i']\) 相对于原区间 \([l_i,r_i]\),有:
\[\begin{aligned}
l_i'&=l+r-r_i\\
r_i'&=l+r-l_i
\end{aligned}
\]
因此可以记录信息,删除后插入。
AC 代码
注意迭代器失效问题。
放一组数据供调试
20 20
304918551 41464763 626731291 93384272 932133547 58912715 131988999 702069776 263423490 347646978 59122396 563111221 416760930 459270045 184611400 242744859 821538911 367584997 718440022 971034462
4 11 13 5 7
6 5 10
2 14 20 185648890
2 8 13 39249510
1 2 15
1 3 5
5 10 11 15 16
4 5 7 17 19
6 5 15
3 9 19 742600878
6 4 4
3 1 17 13105838
5 3 5 13 15
3 3 9 720875841
3 7 11 551893354
1 10 20
5 1 6 8 13
5 4 8 11 15
6 4 17
2 2 13 341469949
681515396
67762534
968391129
325124536 341469949 341469949 341469949 341469949 341469949 341469949 341469949 341469949 341469949 341469949 341469949 341469949 106490110 919630569 824229528 740006040 6024361 444670647 185648890
//#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cstdio>
#include<string>
#include<vector>
#include<cmath>
#include<ctime>
#include<deque>
#include<queue>
#include<stack>
#include<list>
#include<set>
using namespace std;
typedef long long ll;
constexpr const int N=1e5,P=1e9+7;
int n;
struct ODT{
struct node{
int l,r;
mutable int value;
};
friend bool operator <(node a,node b){
return a.l<b.l;
}
set<node>t;
void build(int l,int r){
t.clear();
t.insert({l,r+1});
}
auto split(int x){
auto p=t.lower_bound({x});
if(p!=t.end()&&p->l==x){
return p;
}
p=prev(p);
int l=p->l,r=p->r,value=p->value;
t.erase(p);
t.insert({l,x-1,value});
return t.insert({x,r,value}).first;
}
void assign(int l,int r,int value){
auto pr=split(r+1);
auto pl=split(l);
t.erase(pl,pr);
t.insert({l,r,value});
}
void add(int l,int r,int x){
auto pr=split(r+1);
auto pl=split(l);
for(auto i=pl;i!=pr;i=next(i)){
i->value=(i->value + x)%P;
}
}
int sum(int l,int r){
auto pr=split(r+1);
auto pl=split(l);
int ans=0;
for(auto i=pl;i!=pr;i=next(i)){
ans=(ans + i->value * (i->r - i->l + 1ll) )%P;
}
return ans;
}
void copy(int l1,int r1,int l2,int r2){
auto pr1=split(r1+1);
auto pl1=split(l1);
vector<node>s;
for(auto i=pl1;i!=pr1;i=next(i)){
s.push_back(*i);
}
auto pr2=split(r2+1);
auto pl2=split(l2);
t.erase(pl2,pr2);
for(auto i:s){
t.insert({i.l+l2-l1,i.r+r2-r1,i.value});
}
}
void swap(int l1,int r1,int l2,int r2){
if(l1>l2){
std::swap(l1,l2);
std::swap(r1,r2);
}
auto pr2=split(r2+1);
auto pl2=split(l2);
auto pr1=split(r1+1);
auto pl1=split(l1);
vector<node>s1,s2;
for(auto i=pl1;i!=pr1;i=next(i)){
s1.push_back(*i);
}
for(auto i=pl2;i!=pr2;i=next(i)){
s2.push_back(*i);
}
t.erase(pl1,pr1);
pr2=split(r2+1);
pl2=split(l2);
t.erase(pl2,pr2);
for(auto i:s1){
t.insert({i.l+l2-l1,i.r+r2-r1,i.value});
}
for(auto i:s2){
t.insert({i.l+l1-l2,i.r+r1-r2,i.value});
}
}
void reverse(int l,int r){
if(l>r){
std::swap(l,r);
}
auto pr=split(r+1);
auto pl=split(l);
vector<node>s;
for(auto i=pl;i!=pr;i=next(i)){
s.push_back(*i);
}
t.erase(pl,pr);
for(auto i:s){
t.insert({l+r-i.r,l+r-i.l,i.value});
}
}
}t;
main(){
/*freopen("test.in","r",stdin);
freopen("test.out","w",stdout);*/
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int m;
cin>>n>>m;
t.build(1,n);
for(int i=1;i<=n;i++){
int a;
cin>>a;
t.assign(i,i,a);
}
while(m--){
int op,l1,r1,l2,r2,x;
cin>>op>>l1>>r1;
switch(op){
case 1:
cout<<t.sum(l1,r1)<<'\n';
break;
case 2:
cin>>x;
t.assign(l1,r1,x);
break;
case 3:
cin>>x;
t.add(l1,r1,x);
break;
case 4:
cin>>l2>>r2;
t.copy(l1,r1,l2,r2);
break;
case 5:
cin>>l2>>r2;
t.swap(l1,r1,l2,r2);
break;
case 6:
t.reverse(l1,r1);
break;
}
}
for(int i=1;i<=n;i++){
cout<<t.sum(i,i)<<' ';
}
cout<<'\n';
cout.flush();
/*fclose(stdin);
fclose(stdout);*/
return 0;
}

浙公网安备 33010602011771号