(这是个双倍经验呀!

题目描述

维护一个可以支持插入、删除、翻转、区间赋值、求和、求值和求最大子段和操作的序列。(真·简洁)

solution

基本不用什么神奇操作,平衡树硬上就行。(我用的 Splay )

不太一样的是建树可以模仿线段树建法(据说会快一点)


其中,

1.翻转,区间赋值来打两种标记。

2.求最大子段和要设最大子段和,最大前缀和最大后缀三种变量。(不太清楚的可以先去做做小鲦逛公园


再注意一下,

1.下传标记时,先区间赋值再翻转。

(因为区间赋值改变 \(val\) ,翻转改变 \(id\) , \(id\) 要影响 \(val\) )

2.翻转时,最大前缀和最大后缀要交换。

(因为翻转后,后面的到了前面,前面的到了后面,顺序改变了)

3.平时讲的把一个区间 \([l,r]\) 拉出来是通过把区间外前面的第一个点拉到根后再将区间外后面的第一个点拉到根右孩子树的根上。

实际操作时下标要集体右移一位,因为如果区间为整个数组时要把 \(0\) 拉到根上去,那不就乱了吗!

其实上述情况打文艺平衡树的时候就有了,但再次注意的是这题输入的 \(posi\) 和 \(tot\) 也要在表示区间的时候进行下标的转化。


具体的看看代码吧(马蜂可看,比较清奇,但是长死了,有点烦)

#include<bits/stdc++.h>
#define ls(i) spl[i].ch[0]//左孩子
#define rs(i) spl[i].ch[1]//右孩子
#define fa(i) spl[i].fa//粑粑
#define val(i) spl[i].val//点权值
#define num(i) spl[i].num//子树权值和
#define siz(i) spl[i].siz//字数大小
#define lzy(i) spl[i].lzy//翻转标记
#define mdf(i) spl[i].mdf//区间赋值标记
#define mx(i) spl[i].mx//最大子段和
#define lmx(i) spl[i].lmx//最大前缀
#define rmx(i) spl[i].rmx//最大后缀
//看把孩子逼的
#define reg register
using namespace std;
typedef long long ll;
const int N=1e6+10;
const int INF=0x3f3f3f3f;
int n,m,root,cnt,a[N],id[N];
char s[24];
queue<int> que;
struct Splay{int ch[2],fa,val,num,siz,lzy,mdf,mx,lmx,rmx;}spl[N];
inline int imax(int a,int b){return a>b?a:b;}
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
inline void pushup(int now){
siz(now)=siz(ls(now))+siz(rs(now))+1;
num(now)=num(ls(now))+num(rs(now))+val(now);
int plu=rmx(ls(now))+lmx(rs(now))+val(now);
mx(now)=imax(imax(mx(ls(now)),mx(rs(now))),plu);
lmx(now)=imax(lmx(ls(now)),lmx(rs(now))+num(ls(now))+val(now));
rmx(now)=imax(rmx(rs(now)),rmx(ls(now))+num(rs(now))+val(now));
}
inline void pushdown(int now){
if(mdf(now)){
mdf(now)=lzy(now)=0;
if(ls(now)){
mdf(ls(now))=1;val(ls(now))=val(now);
num(ls(now))=siz(ls(now))*val(ls(now));
}
if(rs(now)){
mdf(rs(now))=1;val(rs(now))=val(now);
num(rs(now))=siz(rs(now))*val(rs(now));
}
if(val(now)>0){
if(ls(now))mx(ls(now))=lmx(ls(now))=rmx(ls(now))=num(ls(now));
if(rs(now))mx(rs(now))=lmx(rs(now))=rmx(rs(now))=num(rs(now));
}
else {
if(ls(now))mx(ls(now))=val(ls(now)),lmx(ls(now))=rmx(ls(now))=0;
if(rs(now))mx(rs(now))=val(rs(now)),lmx(rs(now))=rmx(rs(now))=0;
}
}
if(lzy(now)){
lzy(ls(now))^=1;lzy(rs(now))^=1;lzy(now)^=1;
swap(ls(ls(now)),rs(ls(now)));
swap(ls(rs(now)),rs(rs(now)));
swap(lmx(ls(now)),rmx(ls(now)));
swap(lmx(rs(now)),rmx(rs(now)));
}
}
inline void rotate(int now){
int nxt=fa(now),nnt=fa(nxt);
int k1=rs(nxt)==now,k2=rs(nnt)==nxt;
int pre=spl[now].ch[k1^1];
spl[nnt].ch[k2]=now; fa(now)=nnt;
spl[nxt].ch[k1]=pre; fa(pre)=nxt;
spl[now].ch[k1^1]=nxt; fa(nxt)=now;
pushup(nxt);pushup(now);
}//虽然肯定会跑得慢,但真tm好看
inline void splay(int now,int S){
while(fa(now)!=S){
int nxt=fa(now),nnt=fa(nxt);
int k1=rs(nxt)==now,k2=rs(nnt)==nxt;
if(nnt!=S)(k1^k2)?rotate(now):rotate(nxt);
rotate(now);
}
if(!S)root=now;
}
inline void build(int lt,int rt,int mi){
if(lt>rt)return ;
int mid=(lt+rt)>>1,now=id[mid],pre=id[mi];
if(lt==rt){
siz(now)=1;
if(a[lt]>0)mx(now)=lmx(now)=rmx(now)=a[lt];
else mx(now)=a[lt],lmx(now)=rmx(now)=0;
}
else {
build(lt,mid-1,mid);
build(mid+1,rt,mid);
}
val(now)=a[mid];fa(now)=pre;
pushup(now);
spl[pre].ch[mid>=mi]=now;
}
inline int find(int now,int siz){
pushdown(now);
int sizz=siz(ls(now));
if(siz<=sizz)return find(ls(now),siz);
else if(siz==sizz+1)return now;
else return find(rs(now),siz-sizz-1);
}
inline void insert(int now,int sum){
for(int i=1;i<=sum;++i){
a[i]=read();
if(!que.empty()){
id[i]=que.front();
que.pop();
}
else {
id[i]=++cnt;
}
}
build(1,sum,0);
int mid=(1+sum)>>1,it=id[mid];
int lt=find(root,now+1);
int rt=find(root,now+2);
splay(lt,0);splay(rt,lt);
ls(rt)=it;fa(it)=rt;
pushup(rt);pushup(root);
}
inline void split(int now){
if(!now)return ;
split(ls(now));split(rs(now));
que.push(now);
ls(now)=rs(now)=val(now)=num(now)=siz(now)=0;
lzy(now)=mdf(now)=mx(now)=lmx(now)=rmx(now)=0;
}
inline int divid(int lt,int rt){
lt=find(root,lt);rt=find(root,rt);
//一定要返回去看,因为这些坐标是提前对应好的
splay(lt,0);splay(rt,lt);
return ls(rt);
}
inline void delet(int lt,int rt){
int now=divid(lt,rt),nxt=fa(now);
split(now);
ls(nxt)=0;
pushup(nxt);pushup(root);
}
inline void modify(int lt,int rt,int val){
int now=divid(lt,rt),nxt=fa(now);
mdf(now)=1;val(now)=val;
num(now)=siz(now)*val(now);
if(val>0)mx(now)=lmx(now)=rmx(now)=num(now);
else mx(now)=val,lmx(now)=rmx(now)=0;
pushup(nxt);pushup(root);
}
inline void reverse(int lt,int rt){
int now=divid(lt,rt),nxt=fa(now);
if(!mdf(now)){
lzy(now)^=1;
swap(ls(now),rs(now));
swap(lmx(now),rmx(now));
pushup(nxt);pushup(root);
}
}
inline int getsum(int lt,int rt){
int now=divid(lt,rt);
return num(now);
}
inline int getmxs(int lt,int rt){
lt=find(root,lt);rt=find(root,rt);
//一定要返回去看,因为这些坐标是提前对应好的
splay(lt,0);splay(rt,lt);
return mx(ls(rt));
}
inline int getnum(int lt){
lt=find(root,lt+1);
return val(lt);
}
int main(){
n=read();m=read();
for(int i=2;i<=n+1;++i){
a[i]=read();id[i]=i;
}
mx(0)=a[1]=a[n+2]=-INF;id[1]=1;id[n+2]=n+2;
//因为不能存0,所以集体右移一位了
build(1,n+2,0);cnt=n+2;root=(cnt+1)>>1;
while(m--){
scanf("%s",s);
if(s[0]=='I'){
int posi=read(),tot=read();
insert(posi,tot);
}
else if(s[0]=='D'){
int posi=read(),tot=read();
delet(posi,posi+tot+1);
}
else if(s[2]=='K'){
int posi=read(),tot=read(),c=read();
modify(posi,posi+tot+1,c);
}
else if(s[0]=='R'){
int posi=read(),tot=read();
reverse(posi,posi+tot+1);
}
else if(s[0]=='G'&&s[3]=='-'){
int posi=read(),tot=read();
printf("%d\n",getsum(posi,posi+tot+1));
}
else if(s[0]=='M'&&s[3]=='-'){
int posi=read(),tot=read();
printf("%d\n",getmxs(posi,posi+tot+1));
}
else {
int posi=read();
printf("%d\n",getnum(posi));
}
}
return 0;
}

忠告:做这题的时候,佛系一点总不会错(为什么放最后呀。。)

luogu P2710 数列的更多相关文章

  1. luogu 1327 数列排序 & 2017 ACM-ICPC 亚洲区(南宁赛区)网络赛 J题 循环节

    luogu 1327 数列排序 题意 给定一个数列\(\{an\}\),这个数列满足\(ai≠aj(i≠j)\),现在要求你把这个数列从小到大排序,每次允许你交换其中任意一对数,请问最少需要几次交换? ...

  2. Luogu P1062 数列

    Luogu P1062 数列 题目说: 把所有$k$的方幂及所有有限个互不相等的$k$的方幂之和构成一个递增的序列. 这就是说,每一个$k$的方幂只能有或没有. 有为$0$,没有为$1$. 所以这些数 ...

  3. luogu P1182 数列分段Section II

    题目描述 对于给定的一个长度为N的正整数数列A[i],现要将其分成M(M≤N)段,并要求每段连续,且每段和的最大值最小. 关于最大值最小: 例如一数列4 2 4 5 1要分成3段 将其如下分段: [4 ...

  4. Luogu P3901 数列找不同

    由于技术原因,题目我贴不上了,大家点下面的链接自己去看吧^_^ P3901 数列找不同 这题第一眼看去,题面真短,有坑(flag) 在往下面看去,woc数据这么大,你要怎样. 现在一起想想想,超级侦探 ...

  5. luogu P1356 数列的整数性 |动态规划

    题目描述 对于任意一个整数数列,我们可以在每两个整数中间任意放一个符号'+'或'-',这样就可以构成一个表达式,也就可以计算出表达式的值.比如,现在有一个整数数列:17,5,-2,-15,那么就可以构 ...

  6. luogu P1327 数列排序

    题目描述 给定一个数列{an},这个数列满足ai≠aj(i≠j),现在要求你把这个数列从小到大排序,每次允许你交换其中任意一对数,请问最少需要几次交换? 输入格式 第一行,正整数n (n<=10 ...

  7. luogu P1181 数列分段Section I x

    P1181 数列分段Section I 题目描述 对于给定的一个长度为N的正整数数列A[i],现要将其分成连续的若干段,并且每段和不超过M(可以等于M),问最少能将其分成多少段使得满足要求. 输入输出 ...

  8. luogu P4948 数列求和 推式子 简单数学推导 二项式 拉格朗日插值

    LINK:数列求和 每次遇到这种题目都不太会写.但是做法很简单. 终有一天我会成功的. 考虑类似等比数列求和的东西 帽子戏法一下. 设\(f(k)=\sum_{i=1}^ni^ka^i\) 考虑\(a ...

  9. 【题解】Luogu P3901 数列找不同

    我博客中对莫队的详细介绍 原题传送门 不错的莫队练手题 块数就直接取sqrt(n) 对所有询问进行排序 排序第一关键词:l所在第几块,第二关键词:r的位置 考虑Ai不大,暴力开数组 add时如果加之后 ...

随机推荐

  1. .Net RabbitMQ实战指南——RabbitMQ相关概念介绍

    什么是消息中间件 消息(Message)是指在应用间传送的数据.消息可以非常简单,比如只包含文本字符串.JSON等,也可以很复杂,比如内嵌对象. 消息队列中间件(Message Queue Middl ...

  2. TVM适配NN编译Compiler缺陷

    TVM适配NN编译Compiler缺陷 内容纲要 前言 TVM针对VTA的编译流程 自定义VTA架构:TVM的缺陷与性能瓶颈 TVM缺陷与瓶颈 缺陷一:SRAM配置灵活性差 缺陷二:计算阵列配置僵硬 ...

  3. Python批量重命名 工具贴(一)

    说明 由于在处理图片数据和其他数据时,经常需要对数据进行批量重命名操作,每次使用时都需要重写,非常不便,因此记录下重命名代码方便后续使用. 文件结构说明 参数说明: path为输入路径 image_t ...

  4. CentOS 6.x 安装图形界面

    CentOS 6.x 安装图形界面一.首先查看系统的运行级别以及是否安装了桌面环境1.使用命令 runlevel 查看当前系统运行级别[root@42 ~]# runlevelN 32.使用命令 yu ...

  5. 【NX二次开发】Block UI 线宽

    属性说明 常规         类型 描述     BlockID     String 控件ID     Enable     Logical 是否可操作     Group     Logical ...

  6. 【Azure 机器人】微软Azure Bot 编辑器系列(2) : 机器人/用户提问回答模式,机器人从API获取响应并组织答案 (The Bot Framework Composer tutorials)

    欢迎来到微软机器人编辑器使用教程,从这里开始,创建一个简单的机器人. 在该系列文章中,每一篇都将通过添加更多的功能来构建机器人.当完成教程中的全部内容后,你将成功的创建一个天气机器人(Weather ...

  7. iis配置代理服务器解决跨域问题

    iis配置代理服务器解决跨域问题 解决:在发布的项目根目录添加web.config配置文件 在配置文件中system.webServer节点中加入 <?xml version="1.0 ...

  8. 大家看看大佬对Maven仓库的讲解,有何高明之处?

    Maven在某个统一的位置存储所有项目的共享的构件,这个统一的位置,我们就称之为仓库.(仓库就是存放依赖和插件的地方). 分类 maven的仓库只有两大类:1.本地仓库 2.远程仓库,在远程仓库中又分 ...

  9. 【dp】状压dp

    二进制的力量 状态压缩DP 愤怒的小鸟 第一次接触状态压缩DP是在NOIP2016的愤怒的小鸟,当时菜得连题目都没看懂,不过现在回过头来看还是挺简单的,那么我们再来看看这道题吧. 题意&数据范 ...

  10. webapi发布在iis之后报错Http 403.14 error

    服务器是 Windows Server 2008 R2 Enterprise 网上找了很多说是修改webconfig.试过之后没有效果,另外报错了. 最后才找到是因为webapi发布时选择的应用程序的 ...