首页 > 其他分享 >[题解] CF407E k-d-sequence

[题解] CF407E k-d-sequence

时间:2023-11-12 10:35:10浏览次数:33  
标签:sequence int 题解 ansr back stk CF407E ansl ans

k-d-sequence

给你一个长为 \(n\) 的序列,求最长的子区间使得它加入至多 \(k\) 个数后,重排后是公差为 \(d\) 的等差数列。
\(n, k \le 2 \times 10^5\),\(0 \le d \le 10^9\)。

公差是 \(d\) 的等差数列模 \(p\) 的值应该相等,所以把序列按极长模 \(p\) 同余的连续段分组。

对于同一组,我们将每个数都除以 \(d\),然后就转化成了求公差为 \(1\) 的等差数列。

如果一段区间 \([l, r]\) 满足要求,这就相当于要求 \([l, r]\) 中的数是值域上连续的一段且互不相等。然后套上 Good Subsegments 的判定方法就做完了(也就是判定 \(\max - \min - (r - l) \le k\))。

时间复杂度 \(O(n \log n)\)。

constexpr int MAXN = 2e5 + 9, DLT = 1e9 + 1;
int n, k, d, a[MAXN], lst[MAXN], ans = 0, ansl, ansr;
vector<int> stk[2];
map<int, int> vis;

struct Node {
	ll mn, tag;
} sgt[MAXN << 2]; 

void Push_Up(int p) {
	sgt[p].mn = min(sgt[p << 1].mn, sgt[p << 1 | 1].mn);
	return;
}
void Push_Tag(int p, ll k) {
	sgt[p].mn += k, sgt[p].tag += k;
	return;
}
void Push_Down(int p) {
	if (sgt[p].tag) {
		Push_Tag(p << 1, sgt[p].tag);
		Push_Tag(p << 1 | 1, sgt[p].tag);
		sgt[p].tag = 0;
	}
	return;
}
void Build(int L = 1, int R = n, int p = 1) {
	if (L == R) return sgt[p].mn = L - k, void();
	int Mid = L + R >> 1;
	Build(L, Mid, p << 1), Build(Mid + 1, R, p << 1 | 1);
	Push_Up(p); return;
}
void Update(int l, int r, ll k, int L = 1, int R = n, int p = 1) {
	if (l <= L && R <= r) return Push_Tag(p, k);
	Push_Down(p); int Mid = L + R >> 1;
	if (l <= Mid) Update(l, r, k, L, Mid, p << 1);
	if (Mid < r) Update(l, r, k, Mid + 1, R, p << 1 | 1);
	Push_Up(p); return;
}
int Query(int l, int r, int L = 1, int R = n, int p = 1) {
	if (l <= L && R <= r) {
		if (sgt[p].mn > 0) return -1;
		while (L < R) {
			Push_Down(p); int Mid = L + R >> 1;
			if (sgt[p << 1].mn <= 0) R = Mid, p <<= 1;
			else L = Mid + 1, p = (p << 1 | 1);
		}
		return L;
	}
	Push_Down(p); int Mid = L + R >> 1;
	if (r <= Mid) return Query(l, r, L, Mid, p << 1);
	if (Mid < l) return Query(l, r, Mid + 1, R, p << 1 | 1);
	int ret = Query(l, r, L, Mid, p << 1);
	if (~ret) return ret;
	return Query(l, r, Mid + 1, R, p << 1 | 1);
}

int qry(int pos, int L = 1, int R = n, int p = 1) {
	if (L == R) return sgt[p].mn;
	Push_Down(p); int Mid = L + R >> 1;
	if (pos <= Mid) return qry(pos, L, Mid, p << 1);
	else return qry(pos, Mid + 1, R, p << 1 | 1);
}

void slv() {
	n = Read<int>(), k = Read<int>(), d = Read<int>();
	for (int i = 1; i <= n; i ++) a[i] = Read<int>() + DLT, vis[a[i]] = 0;
	for (int i = 1; i <= n; i ++) lst[i] = vis[a[i]], vis[a[i]] = i;
	if (d == 0) {
		for (int l = 1, r; l <= n; l = r + 1) {
			r = l;
			while (r + 1 <= n && a[r + 1] == a[l]) r ++;
			if (r - l + 1 > ans) ans = r - l + 1, ansl = l, ansr = r;
		}
		Write(ansl, ' '), Write(ansr, '\n');
		return;
	}
	Build();
	for (int l = 1, r; l <= n; l = r + 1) {
		r = l; int mx = l;
		while (r + 1 <= n && a[r + 1] % d == a[r] % d) r ++;
		stk[0].clear(), stk[0].emplace_back(l - 1);
		stk[1].clear(), stk[1].emplace_back(l - 1);
		Update(l, r, - (l - 1));
		for (int i = l; i <= r; i ++) {
			cmax(mx, lst[i] + 1), a[i] /= d;
			while (stk[0].size() > 1 && a[stk[0].back()] <= a[i])
				Update(stk[0][stk[0].size() - 2] + 1, stk[0].back(), - a[stk[0].back()]), stk[0].pop_back();
			Update(stk[0].back() + 1, i, a[i]), stk[0].emplace_back(i);
			while (stk[1].size() > 1 && a[stk[1].back()] >= a[i])
				Update(stk[1][stk[1].size() - 2] + 1, stk[1].back(), a[stk[1].back()]), stk[1].pop_back();
			Update(stk[1].back() + 1, i, - a[i]), stk[1].emplace_back(i);
			Update(l, r, -1);
			int j = Query(mx, i);
			if (~j && i - j + 1 > ans) ans = i - j + 1, ansl = j, ansr = i;
		}
	}
	Write(ansl, ' '), Write(ansr, '\n');
	return;
}
``

标签:sequence,int,题解,ansr,back,stk,CF407E,ansl,ans
From: https://www.cnblogs.com/definieren/p/17826822.html

相关文章

  • [题解] CF505E Mr. Kitayuta vs. Bamboos
    Mr.Kitayutavs.Bamboos给定\(n\)个数\(h_{1\dotsn}\)。你需要进行\(m\)轮操作,每轮操作为\(k\)次修改,每次修改可以选择一个数\(h_i\)修改为\(\max(h_i-p,0)\)。每轮操作后每个\(h_i\)将会被修改为\(h_i+a_i\)。你需要最小化最终\(h_{1\cdotsn}\)中......
  • 【题解 P8763】[蓝桥杯 2021 国 ABC] 异或变换
    同楼上dalao做法:#include<iostream>#include<algorithm>#include<cstdio>#include<cmath>#include<cstring>#include<string>#include<cstdlib>#include<bitset>usingnamespacestd;constintN=1e4+10......
  • ABC328题解(C-G)
    A/B较为简单,略去。C预处理一下,然后前缀和就好了。时间复杂度\(O(n)\)。D用链表来记录字符串。注意到每次能够消去意味着链表上连续三个节点拼起来是ABC,然后从左到右一个个算就行了。匹配到的话把三个节点一起删掉。时间复杂度\(O(n)\)。E注意到\(N\le8,M\le28\)......
  • 2022新生赛 玩石头 题解
    这题乍一看是个背包,但是它对背包物品的重量进行了限制,而且我们没有手段得知当前物品是否大于前面所有物品。研究发现,纪念品最大价值不会超过4000.因此我们可以用类似于01背包的做法,以纪念品价值作为重量,纪念品重量作为价值来dp.打表可以发现,在给定数据的范围下,石头塔最多为三十层,......
  • P9836 种树 题解
    蒟蒻在考场上花了2h45minAC本题通过高度求宽度定义一棵树的宽度为它高度的正因数个数我们可以预处理\(10^4\)之内素数。 for(lli=2;i<=10000;i++){ if(ok[i]==0){ ok[i]=i; pr[++nP]=i; } for(llj=1;i*pr[j]<=10000&&j<=nP;j++){ ok[i*pr[j]]=......
  • [题解] CF1327F AND Segments
    ANDSegments有\(m\)个限制\((l,r,x)\)。要计算满足以下条件的长度为\(n\)的序列\(a\)的数量:\(\foralli\in[1,n],0\lea_i<2^k\)。\(\foralli\in[1,m],a_{l_i}\operatorname{and}a_{l_i+1}\operatorname{and}\cdots\operatorname{and}a_{r......
  • 【洛谷 P1035】[NOIP2002 普及组] 级数求和 题解(循环)
    [NOIP2002普及组]级数求和题目描述已知:。显然对于任意一个整数,当足够大的时候,。现给出一个整数,要求计算出一个最小的,使得。输入格式一个正整数。输出格式一个正整数。样例#1样例输入#11样例输出#12提示【数据范围】对于的数据,。【题目来源】NOIP2002普及组第一题......
  • AT_agc057_e 题解
    AT_agc057_e[0]约定\(r_i=\sum\limits_{j=1}^{m}[A_{i,j}\lek]\)\(r^{'}_i=\sum\limits_{j=1}^{m}[B_{i,j}\lek]\)\(c_j=\sum\limits_{i=1}^{n}[A_{i,j}\lek]\)\(c^{'}_j=\sum\limits_{i=1}^{n}[B_{i,j}\lek]\)[1]......
  • [题解] AT_dp_w Intervals
    Intervals有\(m\)条形如\((l,r,a)\)的限制,表示如果\(s_{[l,r]}\)中有1就会有\(a\)的价值。你要求长度为\(n\)的01串的价值的最大值。\(n,m\le2\times10^5\)。将每个限制挂到右端点上,在右端点处计算贡献。然后我们就只关心最后一个1出现的位置了。......
  • 转 问题解决:记录一次Linux服务器根目录突然爆满
    一般跟目录满了,可以重点关注/var这个目录 一、出问题了过了个双休来到公司,同时发现Linux终端的服务器状态中根目录空间直接爆满100%,周五走之前根目录仅仅使用了59%,同时项目服务的后台不停的有日志打印,而且测试的小伙伴说系统登录不上去了。下面记录一下个人排查并解决这个问题......