(这是个双倍经验呀!

题目描述

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

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. GO学习-(30) Go语言操作kafka

    go操作kafka Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者规模的网站中的所有动作流数据,具有高性能.持久化.多副本备份.横向扩展等特点.本文介绍了如何使用Go语言发送和接收 ...

  2. node.js学习(3)模块

    1.创建文件 count.js 2 调用 3 改造 4 调用 5 再改造 6 在再改造

  3. 安装Linux操作系统过程及出现的问题

    写在前面的话:由于是昨天装的,很多图片没来得及及时的保存,只好凭记忆回想,出现的问题只能回忆起大致的操作及应用软件. 另外,目前是小白一枚. 在安装时,我一开始想直接采用硬盘安装,参考帖子:http: ...

  4. 用NVIDIA-TensorRT构造深度神经网络

    用NVIDIA-TensorRT构造深度神经网络 Deploying Deep Neural Networks with NVIDIA TensorRT NVIDIA TensorRT是一个用于生产环 ...

  5. NVIDIA Nsight Systems CUDA 跟踪

    NVIDIA Nsight Systems CUDA 跟踪 CUDA跟踪 NVIDIA Nsight Systems能够捕获有关在概要过程中执行CUDA的信息. 可以在报告的时间轴上收集和呈现以下信息 ...

  6. 24GHz和77GHz毫米波雷达技术细节

    24GHz和77GHz毫米波雷达技术细节 FMCW Radar Sensitivity Measurement Tech Field Test and Raw Data Analysis Capabi ...

  7. python_selenium_PO模式下显示等待、隐式等待封装,结合Excel读取元素可取默认等待时间配置

    basepage中等待的封装 def implicitly_wait(self): self.driver.implicitly_wait(5)def wait(self): time.sleep(5 ...

  8. java8 函数式编程接口

    java8 函数式接口java.util.function.* @param T 入参类型 @param R 出参类型 1. Function <T,R> 例: Function<I ...

  9. springboot的restful风格获取请求中携带的参数

    http://localhost:8080/emp/1 有以上请求,我们controller要怎么获取请求中传递的参数1呢? 通过PathVariable注解,如下: @DeleteMapping(& ...

  10. hash表及带注释插头dp

    struct hash_map { node s[SZ+10];int e,adj[SZ+10]; inline void init(){e=0;memset(adj,0,sizeof(adj));} ...