1 条题解
-
0
自动搬运
来自洛谷,原作者为

NaCly_Fish
北海虽赊,扶摇可接。搬运于
2025-08-24 22:09:51,当前版本为作者最后更新于2019-10-11 13:33:21,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
updated:这份代码现在可以通过了
建议使用 FHQTreap 或 LeafyTree 等可以分裂、合并的平衡树来实现。
本做法用的是 FHQTreap。这是一个时间复杂度正确的做法
众所周知,如果没有区间赋值操作,ODT会被卡飞,不过这题可以用可持久化平衡树来实现。对于 操作,这里就不做过多解释,做过 【模板】可持久化文艺平衡树 的话可以很容易写出来。
对于 操作,我们钦定 ,然后暴力把序列分成 段,把第 段和第 段交换位置后再合并即可。
最后是 操作,还是分成 个区间,要被覆盖掉的区间就扔掉,然后从另外一个区间的根节点直接复制一份,再合并回去就好了。
这题需要可持久化的原因,就是 操作要复制节点。
由于此题的 达到了 ,所以需要定期重构,以节省空间。
数组最大只能开到 ,所以只要发现节点数多于 就线性重构一波。细节非常多,很不好写。
代码如下:#include<cstdio> #include<iostream> #include<cstring> #include<cmath> #include<algorithm> #include<ctime> #define N 4000003 #define ls son[u][0] #define rs son[u][1] #define reg register #define ll long long #define p 1000000007 #define mid ((l+r)>>1) using namespace std; inline void read(int &x){ x = 0; char c = getchar(); while(c<'0'||c>'9') c = getchar(); while(c>='0'&&c<='9'){ x = (x<<3)+(x<<1)+(c^48); c = getchar(); } } void print(int x){ if(x>9) print(x/10); putchar(x%10+'0'); } inline int add(int x,int y){ return x+y>=p?x+y-p:x+y; } int a[N],son[N][2],size[N]; int sum[N],taga[N],tagc[N],b[300003]; bool rev[N]; int n,q,rt,cnt,tp; inline int neww(int x){ int u = ++cnt; size[u] = 1; a[u] = sum[u] = x; tagc[u] = -1; ls = rs = taga[u] = rev[u] = 0; return cnt; } inline int copy(int u){ int v = ++cnt; a[v] = a[u],sum[v] = sum[u]; son[v][0] = ls,son[v][1] = rs; rev[v] = rev[u]; size[v] = size[u]; taga[v] = taga[u]; tagc[v] = tagc[u]; return v; } inline void pushup(int u){ size[u] = size[ls]+size[rs]+1; sum[u] = add(add(sum[ls],sum[rs]),a[u]); } inline void pushr(int u){ swap(ls,rs); rev[u] ^= 1; } inline void pusha(int u,int k){ a[u] = add(a[u],k); taga[u] = add(taga[u],k); sum[u] = (sum[u]+(ll)size[u]*k)%p; } inline void pushc(int u,int k){ taga[u] = 0; tagc[u] = a[u] = k; sum[u] = (ll)size[u]*k%p; } inline void pushdown(int u){ if(tagc[u]!=-1||taga[u]||rev[u]){ if(ls) ls = copy(ls); if(rs) rs = copy(rs); } if(tagc[u]!=-1){ if(ls) pushc(ls,tagc[u]); if(rs) pushc(rs,tagc[u]); tagc[u] = -1; } if(taga[u]){ if(ls) pusha(ls,taga[u]); if(rs) pusha(rs,taga[u]); taga[u] = 0; } if(!rev[u]) return; if(ls) pushr(ls); if(rs) pushr(rs); rev[u] = 0; } int merge(int u,int v){ if(!u||!v) return u|v; if(rand()%(size[u]+size[v])<size[u]){ pushdown(u),u = copy(u); son[u][1] = merge(son[u][1],v); pushup(u); return u; }else{ pushdown(v),v = copy(v); son[v][0] = merge(u,son[v][0]); pushup(v); return v; } } int merge1(int u,int v){ if(!u||!v) return u|v; if(rand()%(size[u]+size[v])<size[u]){ son[u][1] = merge1(son[u][1],v); pushup(u); return u; }else{ son[v][0] = merge1(u,son[v][0]); pushup(v); return v; } } void split(int cur,int k,int &u,int &v){ if(!cur){ u = v = 0; return; } pushdown(cur); if(size[son[cur][0]]<k){ u = copy(cur); split(son[u][1],k-size[son[u][0]]-1,son[u][1],v); pushup(u); }else{ v = copy(cur); split(son[v][0],k,u,son[v][0]); pushup(v); } } inline void reverse(int l,int r){ int x,y,z; split(rt,l-1,x,y); split(y,r-l+1,y,z); y = copy(y); pushr(y); rt = merge(merge(x,y),z); } inline void change(int l,int r,int k){ int x,y,z; split(rt,l-1,x,y); split(y,r-l+1,y,z); y = copy(y); pushc(y,k); rt = merge(merge(x,y),z); } inline void modify(int l,int r,int k){ int x,y,z; split(rt,l-1,x,y); split(y,r-l+1,y,z); y = copy(y); pusha(y,k); rt = merge(merge(x,y),z); } inline void swap(int l1,int r1,int l2,int r2){ int v,w,x,y,z; if(l1>l2){ swap(l1,l2); swap(r1,r2); } split(rt,l1-1,v,w); split(w,r1-l1+1,w,x); split(x,l2-r1-1,x,y); split(y,r2-l2+1,y,z); rt = merge(merge(merge(merge(v,y),x),w),z); } inline void paste(int l1,int r1,int l2,int r2){ bool flag = false; int v,w,x,y,z; if(l1>l2){ swap(l1,l2); swap(r1,r2); flag = true; } split(rt,l1-1,v,w); split(w,r1-l1+1,w,x); split(x,l2-r1-1,x,y); split(y,r2-l2+1,y,z); if(flag) w = copy(y); else y = copy(w); rt = merge(merge(merge(merge(v,w),x),y),z); } inline int query(int l,int r){ int x,y,z,res; split(rt,l-1,x,y); split(y,r-l+1,y,z); res = sum[y]; rt = merge(merge(x,y),z); return res; } void dfs(int u){ pushdown(u); if(ls) dfs(ls); b[++tp] = a[u]; if(rs) dfs(rs); } int build(int l,int r){ if(l>r) return 0; int u = neww(b[mid]); ls = build(l,mid-1); rs = build(mid+1,r); pushup(u); return u; } int main(){ srand(time(0)); int op,l1,r1,l2,r2,k; read(n),read(q); for(reg int i=1;i<=n;++i) read(b[i]); rt = build(1,n); while(q--){ read(op),read(l1),read(r1); if(op==1){ print(query(l1,r1)); putchar('\n'); }else if(op==2){ read(k); change(l1,r1,k); }else if(op==3){ read(k); modify(l1,r1,k); }else if(op==4){ read(l2),read(r2); paste(l1,r1,l2,r2); }else if(op==5){ read(l2),read(r2); swap(l1,r1,l2,r2); }else reverse(l1,r1); if(cnt>3600000){ tp = 0; dfs(rt); rt = cnt = 0; rt = build(1,n); } } tp = 0; dfs(rt); for(reg int i=1;i<=n;++i) print(b[i]),putchar(' '); return 0; }
- 1
信息
- ID
- 4256
- 时间
- 3000ms
- 内存
- 128MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者