LGP12263 [STAOI R9] 回听 学习笔记
LGP12263 [STAOI R9] 回听 学习笔记
题意简述
给定一个长为 \(n\) 的数组 \(A\)。
定义“回听”操作为:选择一系列 \(n\) 以内的下标,记该下标集合为 \(S\)。令所有 \(a_{s_i}\) 去到 \(s_{i+1}\) 位置。特别的,令 \(a_{s_{|S|}}\) 去到 \(s_1\) 位置并减掉 \(|S|-1\)(但不能减到 \(0\) 以下)。
定义 \(b_i\) 为一次回听操作后 \(a_i\) 可能产生的最小值。
有 \(m\) 次对 \(A\) 的区间加修改。在每次修改后回答有多少种 \(b_i\) 取值。
\(n,m\le 5\times 10^5\)。\(V\) 经过区间加后会到达long long范围。
做法解析
手玩,你发现:\(b_i\) 要么是 \(j\in[1,i]\) 内最小的 \(a_j\),要么是对于 \(j\in(i,n]\) 最小的 \(a_i-(j-i)\)。如果你只是想单点求 \(b_i\),两个区间加区间最小值的线段树就能搞定。
但是“本质不同的 \(b_i\)”又要怎么搞?这东西复杂度看着就很不简单啊,除非……
除非“本质不同”是个幌子。你分析一下这个东西。你发现,\(b_i\) 随 \(i\) 增加单调不降,并且相邻 \(b_i\) 间差值最多为 \(1\)。这意味着你求出 \(b_1\) 和 \(b_n\) 之后,本质不同的 \(b_i\) 种数就是 \(b_n-b_1+1\)。
为什么呢?这是因为随着 \(i\) 每增加 \(1\),你发现来源于 \((i,n]\) 的那部分答案就会随之增加 \(1\),而来源于 \([1,i]\) 的那部分答案不变。
好说完了。
代码实现
#include <bits/stdc++.h>
using namespace std;
using namespace obasic;
const int MaxN=5e5+5;
const lolo Inf=1e18;
int N,M,A[MaxN],D[MaxN],X,Y,Z;
struct SegTree{
lolo mn[MaxN<<2],tag[MaxN<<2];
int ls(int u){return u<<1;}
int rs(int u){return (u<<1)|1;}
void pushup(int u){mn[u]=min(mn[ls(u)],mn[rs(u)]);}
void build(int u,int cl,int cr,int x[]){
if(cl==cr){mn[u]=x[cl];return;}int cmid=(cl+cr)>>1;
build(ls(u),cl,cmid,x),build(rs(u),cmid+1,cr,x),pushup(u);
}
void maketag(int u,lolo x){mn[u]+=x,tag[u]+=x;}
void pushdown(int u){if(tag[u])maketag(ls(u),tag[u]),maketag(rs(u),tag[u]),tag[u]=0;}
void update(int u,int cl,int cr,int dl,int dr,lolo x){
if(dl<=cl&&cr<=dr){maketag(u,x);return;}
int cmid=(cl+cr)>>1;pushdown(u);
if(dl<=cmid)update(ls(u),cl,cmid,dl,dr,x);
if(dr>cmid)update(rs(u),cmid+1,cr,dl,dr,x);
pushup(u);
}
lolo getmin(int u,int cl,int cr,int dl,int dr){
if(dl<=cl&&cr<=dr)return mn[u];
int cmid=(cl+cr)>>1;lolo res=Inf;pushdown(u);
if(dl<=cmid)minner(res,getmin(ls(u),cl,cmid,dl,dr));
if(dr>cmid)minner(res,getmin(rs(u),cmid+1,cr,dl,dr));
return res;
}
}SgT1,SgT2;
int solve(int p){return min(SgT1.getmin(1,1,N,1,p),max((SgT2.getmin(1,1,N,p,N)+p),0ll));}
int main(){
readis(N,M);
for(int i=1;i<=N;i++)readi(A[i]),D[i]=A[i]-i;
SgT1.build(1,1,N,A),SgT2.build(1,1,N,D);
for(int i=1;i<=M;i++){
readis(X,Y,Z);
SgT1.update(1,1,N,X,Y,Z);
SgT2.update(1,1,N,X,Y,Z);
writil(solve(N)-solve(1)+1);
}
return 0;
}
浙公网安备 33010602011771号