P5350 【序列】
看见一堆人在喷swap毒瘤,其实swap很好写啊。
首先,先在输入后面加上这么一句话:
s.insert(node(n+1,n+n+5,0));
在这个序列后加一个长为n的空序列。
然后保证您的Copy是对的
Copy可以这么写:
void Copy(int l1,int r1,int l2,int r2) {
IT itr=Split(r1+1),itl=Split(l1);
for(tot=0;itl!=itr;++itl)
a[++tot]=l2+itl->l-l1,b[tot]=l2+itl->r-l1,c[tot]=itl->val;
for(int i=1;i<=tot;++i)
Assign(a[i],b[i],c[i]);
}
大概就是存一下Copy过去对应的区间是什么,然后Assign过去就好了。少对指针操作,因为指针太玄学了qwq
接着Swap,看看代码就能懂……
void Swap(int l1,int r1,int l2,int r2) {
Copy(l1,r1,n+1,n+r1-l1+1);
Copy(l2,r2,l1,r1);
Copy(n+1,n+r1-l1+1,l2,r2);
}
真的一点都不毒瘤!!!
只要您能理解swap整数时的内部操作:
void swap(int &a,int &b) {
int tmp;
tmp=a;
a=b;
b=tmp;
}
然后区间加,区间求和,区间推平都不讲了。
区间翻转
先看代码,看懂了就不用看说明了。
void Reverse(int l,int r) {
IT itr=Split(r+1),itl=Split(l);
vector<node>vec;
for(IT it=itl;it!=itr;++it)
vec.push_back(node(it->l,it->r,it->val));
s.erase(itl,itr);
int t=l;
for(int i=vec.size()-1;i>=0;--i)
s.insert(node(t,t+vec[i].r-vec[i].l,vec[i].val)),t+=vec[i].r-vec[i].l+1;
}
说明:就是先把节点存起来,把区间删掉,然后把节点倒着插回去。
其实我感觉ODT的操作都很好懂,因为全是暴力……
然后关于输出,由于每个节点存的是区间,所以要考虑如何输出区间长度遍。然后瞎搞搞出来了一个东西……
void Print(){
IT it=s.begin();
int print=0;
while(print<n) {
for(int i=it->l;i<=it->r;++i)
{
printf("%lld ",it->val);
++print;
if(print==n)return (void)puts("");
}
++it;
}
}
完整版代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod=1000000007;
const int N=300005;
int n,m;
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 &rhs)const{return l<rhs.l;}
};
set<node>s;
#define IT set<node>::iterator
void Print(){
IT it=s.begin();
int print=0;
while(print<n) {
for(int i=it->l;i<=it->r;++i)
{
printf("%lld ",it->val);
++print;
if(print==n)return (void)puts("");
}
++it;
}
}
IT Split(int pos){
IT it=s.lower_bound(node(pos));
if(it!=s.end()&&it->l==pos)return it;
--it;
int ll=it->l,rr=it->r,v=it->val;
s.erase(it);
s.insert(node(ll,pos-1,v));
return s.insert(node(pos,rr,v)).first;
}
int Sum(int l,int r){
int res=0;
IT itr=Split(r+1),itl=Split(l);
for(;itl!=itr;++itl)
res=(res+(itl->r-itl->l+1)*itl->val)%mod;
return (int)res;
}
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));
}
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;
}
int a[N],b[N],c[N],tot;
void Copy(int l1,int r1,int l2,int r2) {
IT itr=Split(r1+1),itl=Split(l1);
for(tot=0;itl!=itr;++itl)
a[++tot]=l2+itl->l-l1,b[tot]=l2+itl->r-l1,c[tot]=itl->val;
for(int i=1;i<=tot;++i)
Assign(a[i],b[i],c[i]);
}
void Swap(int l1,int r1,int l2,int r2) {
Copy(l1,r1,n+1,n+r1-l1+1);
Copy(l2,r2,l1,r1);
Copy(n+1,n+r1-l1+1,l2,r2);
}
void Reverse(int l,int r) {
IT itr=Split(r+1),itl=Split(l);
vector<node>vec;
for(IT it=itl;it!=itr;++it)
vec.push_back(node(it->l,it->r,it->val));
s.erase(itl,itr);
int t=l;
for(int i=vec.size()-1;i>=0;--i)
s.insert(node(t,t+vec[i].r-vec[i].l,vec[i].val)),t+=vec[i].r-vec[i].l+1;
}
signed main() {
scanf("%lld%lld",&n,&m);
for(int i=1,x;i<=n;++i)
scanf("%d",&x),s.insert(node(i,i,x));
s.insert(node(n+1,n+n+5,0));
while(m--) {
int opt;
scanf("%lld",&opt);
if(opt==1) {
int l,r;
scanf("%lld%lld",&l,&r);
printf("%d\n",Sum(l,r));
//Print();
}
if(opt==2) {
int l,r,val;
scanf("%lld%lld%lld",&l,&r,&val);
Assign(l,r,val);
//Print();
}
if(opt==3) {
int l,r,val;
scanf("%lld%lld%lld",&l,&r,&val);
Add(l,r,val);
//Print();
}
if(opt==4) {
int l1,r1,l2,r2;
scanf("%lld%lld%lld%lld",&l1,&r1,&l2,&r2);
Copy(l1,r1,l2,r2);
//Print();
}
if(opt==5) {
int l1,r1,l2,r2;
scanf("%lld%lld%lld%lld",&l1,&r1,&l2,&r2);
Swap(l1,r1,l2,r2);
//Print();
}
if(opt==6) {
int l,r;
scanf("%lld%lld",&l,&r);
Reverse(l,r);
//Print();
}
}
Print();
return 0;
}
路漫漫其修远兮,吾将上下而求索