【题解】ABC248Ex - Beautiful Subsequences
给定一个排列和常数 ,求有多少子区间满足区间 。
我们固定右端点统计有多少合法左端点的答案。观察到 很小,所以等价于对于每个 统计有多少 满足 ,其中 。
也就是说我们只用支持更新 即可,而这是后缀最大值/最小值,直接用单调栈维护。那么问题就转化为支持区间加,查询区间中 的数的个数,直接分块即可。
时间复杂度 。
#define N 140005
#define M 380
int n, k, a[N], len, t[M], m; LL ans;
int u[M][N];
#define ll(x) max(x * len, 1)
#define rr(x) min(x * len + len - 1, n)
void add(int l,int r,int val){
if(l / len == r / len){
int id = l / len;
rep(i, l, r)a[i] <= m && u[id][a[i]]--, a[i] += val, a[i] <= m && u[id][a[i]]++;
}
else{
int ld = l / len, rd = r / len, lc = rr(ld), rc = ll(rd);
rep(i, ld + 1, rd - 1)t[i] += val;
rep(i, l, lc)a[i] <= m && u[ld][a[i]]--, a[i] += val, a[i] <= m && u[ld][a[i]]++;
rep(i, rc, r)a[i] <= m && u[rd][a[i]]--, a[i] += val, a[i] <= m && u[rd][a[i]]++;
}
}
int ask(int r,int val){
int id = r / len, sum = 0, l = ll(id);
rep(i, 0, id - 1)if(val - t[i] > 0)sum += u[i][val - t[i]];
rep(i, l, r)sum += (a[i] + t[id] == val);
return sum;
}
int mx[N], mn[N], lt, rt, v[N];
int main() {
read(n, k), len = sqrt(n) + 0.5, m = n + k;
rp(i, n)a[i] = i, u[i / len][i] = 1;
rp(i, n){
int x; read(x), v[i] = x;
while(lt && v[mx[lt]] < x){
add(mx[lt - 1] + 1, mx[lt], x - v[mx[lt]]), lt--;
}mx[++lt] = i;
while(rt && v[mn[rt]] > x){
add(mn[rt - 1] + 1, mn[rt], v[mn[rt]] - x), rt--;
}mn[++rt] = i;
rep(w, 0, k)ans += ask(i, i + w);
}
printf("%lld\n", ans);
return 0;
}
作者:7KByte
出处:https://www.cnblogs.com/7KByte/p/16163047.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
· 零经验选手,Compose 一天开发一款小游戏!