【题解】ABC248Ex - Beautiful Subsequences

给定一个排列和常数 K3,求有多少子区间满足区间 maxminRL+K

我们固定右端点统计有多少合法左端点的答案。观察到 K 很小,所以等价于对于每个 R 统计有多少 L 满足 R=maxmin+Lw,其中 w[0,K]

也就是说我们只用支持更新 maxmin 即可,而这是后缀最大值/最小值,直接用单调栈维护。那么问题就转化为支持区间加,查询区间中 =x 的数的个数,直接分块即可。

时间复杂度 O(KNN)

#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 国际」许可协议进行许可。

posted @   7KByte  阅读(169)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
· 零经验选手,Compose 一天开发一款小游戏!
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
点击右上角即可分享
微信分享提示