【LGP5350】序列
可能\(\operatorname{fhq\ treap}\)能做,但是珂朵莉树显然更好写
珂朵莉树是个很玄学的东西啊,就是直接使用\(\operatorname{std::set}\)维护每一段权值相等的连续段,之后暴力这些连续段就好了
在数据随机的意义下且有区间推平操作的时候,连续段的个数是期望\(\log\)的
核心操作是\(split(pos)\),就是把\(pos\)分裂出来,返回一个以\(pos\)为开头的连续段的迭代器
具体实现这样就好了
struct node {
int l,r;
mutable int v;
bool operator<(const node &A) const {if(l==A.l) return r<A.r;return l<A.l;}
};
std::set<node> s;
inline St split(int pos) {
St it=s.lower_bound((node){pos,-1,0});
if(it!=s.end()&&it->l==pos) return it;
--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;
}
我们操作区间\([l,r]\)的时候,只需要\(x=split(l),y=split(r+1)\),那么对应的\([x,y)\)就是我们要操作的迭代器了
暴力操作这些迭代器即可
一个非常关键的问题,就是我们必须先\(split(r+1)\),之后再\(split(l)\),如果先\(split(l)\)的话可能在\(split(r+1)\)的时候会删除\(l\)所在的区间导致迭代器失效
代码
#include<bits/stdc++.h>
#define re register
#define LL long long
#define St std::set<node>::iterator
inline int read() {
char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
const int mod=1e9+7;
const int maxn=3e5+5;
int lx[maxn],ry[maxn],t[maxn],n,m;
struct node {
int l,r;
mutable int v;
bool operator<(const node &A) const {if(l==A.l) return r<A.r;return l<A.l;}
};
std::set<node> s;
inline St split(int pos) {
St it=s.lower_bound((node){pos,-1,0});
if(it!=s.end()&&it->l==pos) return it;
--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 del(int l,int r) {
St itr=split(r+1),itl=split(l);
s.erase(itl,itr);
}
inline void pia(int l,int r,int v) {
St itr=split(r+1),it=split(l);
s.erase(it,itr);
s.insert((node){l,r,v});
}
inline void add(int l,int r,int val) {
St itr=split(r+1),it=split(l);
for(;it!=itr;++it) it->v=(it->v+val)%mod;
}
inline int calc(int l,int r) {
int ans=0;
St itr=split(r+1),it=split(l);
for(;it!=itr;++it) ans=(ans+1ll*it->v*(it->r-it->l+1)%mod)%mod;
return ans;
}
inline void rev(int l,int r) {
int tot=0,len=r+l;
St itr=split(r+1),it=split(l);
St a=it;
for(;it!=itr;++it) lx[++tot]=(*it).l,ry[tot]=(*it).r,t[tot]=(*it).v;
s.erase(a,itr);
for(re int i=1;i<=tot;i++)
s.insert((node){len-ry[i],len-lx[i],t[i]});
}
inline void move(int l1,int r1,int l2,int r2) {
int tot=0;
St itr=split(r1+1),it=split(l1);
for(;it!=itr;++it) lx[++tot]=(*it).l,ry[tot]=(*it).r,t[tot]=(*it).v;
itr=split(r2+1),it=split(l2);
s.erase(it,itr);
for(re int i=1;i<=tot;i++)
s.insert((node){lx[i]+l2-l1,ry[i]+r2-r1,t[i]});
}
inline void Swap(int l1,int r1,int l2,int r2) {
int tot=0,cnt=0;
St itr=split(r1+1),it=split(l1);
for(;it!=itr;++it) lx[++tot]=(*it).l,ry[tot]=(*it).r,t[tot]=(*it).v;
cnt=tot;itr=split(r2+1),it=split(l2);
for(;it!=itr;++it) lx[++tot]=(*it).l,ry[tot]=(*it).r,t[tot]=(*it).v;
del(l1,r1),del(l2,r2);
for(re int i=1;i<=cnt;i++)
s.insert((node){lx[i]+l2-l1,ry[i]+r2-r1,t[i]});
for(re int i=cnt+1;i<=tot;i++)
s.insert((node){lx[i]-l2+l1,ry[i]-r2+r1,t[i]});
}
inline void out() {
St it=s.begin();
for(;it!=s.end();++it)
for(re int j=it->l;j<=it->r;++j)
printf("%d ",it->v);
puts("");
}
int main() {
n=read(),m=read();
for(re int i=1;i<=n;i++) s.insert((node){i,i,read()});
int op,l,r,x,y,val;
while(m--) {
op=read(),l=read(),r=read();
if(op==1) printf("%d\n",calc(l,r));
if(op==2||op==3) val=read();
if(op==2) pia(l,r,val);
if(op==3) add(l,r,val);
if(op==6) rev(l,r);
if(op==4||op==5) x=read(),y=read();
if(op==4) move(l,r,x,y);
if(op==5) Swap(l,r,x,y);
}
out();
return 0;
}
【LGP5350】序列的更多相关文章
- 【夯实PHP基础】UML序列图总结
原文地址 序列图主要用于展示对象之间交互的顺序. 序列图将交互关系表示为一个二维图.纵向是时间轴,时间沿竖线向下延伸.横向轴代表了在协作中各独立对象的类元角色.类元角色用生命线表示.当对象存在时,角色 ...
- Windows10-UWP中设备序列显示不同XAML的三种方式[3]
阅读目录: 概述 DeviceFamily-Type文件夹 DeviceFamily-Type扩展 InitializeComponent重载 结论 概述 Windows10-UWP(Universa ...
- 软件工程里的UML序列图的概念和总结
俗话说,自己写的代码,6个月后也是别人的代码……复习!复习!复习! 软件工程的一般开发过程:愿景分析.业务建模,需求分析,健壮性设计,关键设计,最终设计,实现…… 时序图也叫序列图(交互图),属于软件 ...
- python序列,字典备忘
初识python备忘: 序列:列表,字符串,元组len(d),d[id],del d[id],data in d函数:cmp(x,y),len(seq),list(seq)根据字符串创建列表,max( ...
- BZOJ 1251: 序列终结者 [splay]
1251: 序列终结者 Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 3778 Solved: 1583[Submit][Status][Discu ...
- 最长不下降序列nlogn算法
显然n方算法在比赛中是没有什么用的(不会这么容易就过的),所以nlogn的算法尤为重要. 分析: 开2个数组,一个a记原数,f[k]表示长度为f的不下降子序列末尾元素的最小值,tot表示当前已知的最长 ...
- [LeetCode] Sequence Reconstruction 序列重建
Check whether the original sequence org can be uniquely reconstructed from the sequences in seqs. Th ...
- [LeetCode] Binary Tree Longest Consecutive Sequence 二叉树最长连续序列
Given a binary tree, find the length of the longest consecutive sequence path. The path refers to an ...
- [LeetCode] Repeated DNA Sequences 求重复的DNA序列
All DNA is composed of a series of nucleotides abbreviated as A, C, G, and T, for example: "ACG ...
随机推荐
- Linux 系统分区与目录介绍
分区 分区类型 主分区:总共最多只能分四个 扩展分区: 只能有一个,也算作主分区的一种,也就是说主分区加扩展分区最多有四个. 但是扩展分区不能存储数据和格式化,必须再划分成逻辑分区才能使用. 逻辑分区 ...
- MySql 字段类型对应 Java 实体类型
前言 MySQL Connector/J 对于 MySql 数据类型和 Java 数据类型之间的转换是很灵活的: 一般来讲,任何 MySql 数据类型都可以被转换为一个 java.lang.Strin ...
- JsJquery小技巧
JS对URL编码 :encodeURI() .Net对URL解码:HttpUtility.UrlDecode() 格式化输出百分数 function formatePercent(data){ ...
- Openstack Nova 源码分析 — RPC 远程调用过程
目录 目录 Nova Project Services Project 的程序入口 setuppy Nova中RPC远程过程调用 nova-compute RPC API的实现 novacompute ...
- [转]C# 将类的内容写成JSON格式的字符串
将类的内容写入到JSON格式的字符串中 本例中建立了Person类,赋值后将类中内容写入到字符串中 运行本代码需要添加引用动态库Newtonsoft.Json 程序代码: using System; ...
- Area--->AreaRegistrationContext.MapRoute
文章引导 MVC路由解析---IgnoreRoute MVC路由解析---MapRoute MVC路由解析---UrlRoutingModule Area的使用 Area--->AreaRegi ...
- 在jsp页面直接读取mysql数据库显示数据
闲来无事,学学java,虽说编程语言相通,但是接触一门新知识还是有些疑惑,边学边记录,方便以后温故. 直接给出代码: <%@page import="java.sql.ResultSe ...
- Metasploit 如何使用Exploits(漏洞)
在Metasploit中选择一个漏洞利用程序将'exploit'和'check'命令添加到msfconsole. msf > use exploit/windows/smb/ms09_050_s ...
- 剑指offer——11矩阵覆盖
题目描述 我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形.请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法? 题解: 使用递归或者动态规划,明显,递归没有动态规划优 ...
- jQuery Ajax请求 .net 一般处理程序
初学ajax 一个简单的功能,调试了2个小时,代码如下虽然成功了 但是有错误 <!DOCTYPE html> <html> <head> <meta http ...