首页 > 其他分享 >CF1777C题解

CF1777C题解

时间:2023-10-24 19:23:21浏览次数:32  
标签:CF1777C minn rs int 题解 void mid res

  • 分析

    看到题面里面的子序列觉得很恶心,如果是子段感觉就会比较好做。
    如果直接填上子序列中间的空隙就可能会取一些比必须要取的数更大或者更小的数,影响我们的答案。
    那么就可以直接排序,使得子序列中间的空隙的数必然 \(\geq\) 左端且 \(\leq\) 右端,不会影响我们的答案(因为极差只看最大最小值)。

    那么问题就变成了选取子段 \([L,R]\) 满足 \(\{x|x\in[1,m]\}\in \{x|(x|a_i, i\in[L,R])\}\)。
    由于一个子段的子段的答案肯定不劣于原子段,考虑two-pointers。
    思路跟NOI2016区间一样,先向右找到合法的右端点 \(r\),然后选取最大的合法左端点 \(l\)。
    对于每个新选择的右端点的答案肯定劣于原来的,所以要右移左端点保证不劣。

    然后用线段树维护区间的最大最小值计算答案。

    寻找合法区间的过程与HH的项链莫队做法大致相同,开一个桶数组,如果要加一个原本桶里面是0的因数就给记录因数个数的变量 \(cnt\) 加一,如果减了一个因数使这个因数的桶里面是0就给\(cnt\)减一。

  • 代码

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
constexpr int MAXN(1000007);
constexpr int INF(0x3f3f3f3f);
int minn[MAXN], maxn[MAXN], a[MAXN], tot[MAXN];
int T, n, m, cnt;
inline void load(int x) {
	for (int i(1); i * i <= x; ++i) {
		if (i * i == x && i <= m)  cnt += (tot[i] == 0), ++tot[i];
		else if (x % i == 0) {
			if (i <= m)  cnt += (tot[i] == 0), ++tot[i];
			if (x / i <= m)  cnt += (tot[x / i] == 0), ++tot[x / i];
		}
	}
}
inline void unload(int x) {
	for (int i(1); i * i <= x; ++i) {
		if (i * i == x && i <= m)  --tot[i], cnt -= (tot[i] == 0);
		else if (x % i == 0) {
			if (i <= m)  --tot[i], cnt -= (tot[i] == 0);
			if (x / i <= m)  --tot[x / i], cnt -= (tot[x / i] == 0);
		}
	}
}
struct SGT{
	#define ls (p << 1)
	#define rs (p << 1 | 1)
	#define mid ((l + r) >> 1)
	inline void pushup(int p) { minn[p] = min(minn[ls], minn[rs]), maxn[p] = max(maxn[ls], maxn[rs]); }
	void build(int p, int l, int r) {
		if (l == r)  return minn[p] = a[l], maxn[p] = a[l], void();
		build(ls, l, mid), build(rs, mid + 1, r);
		pushup(p);
	}
	int qmax(int p, int l, int r, int s, int t) {
		if (s <= l && t >= r)  return maxn[p];
		int res(0);
		if (s <= mid)  res = max(res, qmax(ls, l, mid, s, t));
		if (t > mid)  res = max(res, qmax(rs, mid + 1, r, s, t));
		return res;
	}
	int qmin(int p, int l, int r, int s, int t) {
		if (s <= l && t >= r)  return minn[p];
		int res(INF);
		if (s <= mid)  res = min(res, qmin(ls, l, mid, s, t));
		if (t > mid)  res = min(res, qmin(rs, mid + 1, r, s, t));
		return res;
	}
	#undef ls
	#undef rs
	#undef mid
}Miku;
inline void read(int &temp) { cin >> temp; }
inline void work() {
	int ans(INF), l(1), r(0);
	memset(tot, 0, sizeof(tot));
	cnt = 0;
	read(n), read(m);
	for (int i(1); i <= n; ++i)  read(a[i]);
	sort(a + 1, a + n + 1);
	Miku.build(1, 1, n);
	while (1) {
		while (cnt < m && r <= n)  ++r, load(a[r]);
		if (r > n)  break;
		while (cnt == m && l <= r)  unload(a[l]), ++l;
		ans = min(ans, Miku.qmax(1, 1, n, l - 1, r) - Miku.qmin(1, 1, n, l - 1, r));
	}
	if (ans == INF)  return cout << "-1" << endl, void();
	cout << ans << endl;
}
int main() {
	ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
	read(T);
	while (T--)  work();
	return 0;
}

标签:CF1777C,minn,rs,int,题解,void,mid,res
From: https://www.cnblogs.com/Kazdale/p/17785567.html

相关文章

  • [题解]CF1223F Stack Exterminable Arrays
    CCF出的原题观摩一下。思路首先可以用一个Trie来维护。在这里对本文中的一些变量做一下说明。\(p\)表示当前维护的Trie中,指向的元素编号。\(t_i\)表示在Trie中编号为\(i\)的元素在原序列中的值。\(f_i\)表示在Trie中编号为\(i\)的元素在Trie中的父......
  • CSP-S 2023 题解
    CSP-S2023题解游记打得非常烂。。。也是一个经验的总结吧:T1.密码锁(lock)似乎也没什么好讲的,直接模拟枚举每一种情况即可。放上我的考场代码。#include<bits/stdc++.h>usingnamespacestd;intn,a[10][8],b[2][90][8],ans=0,len,l;intread(){intx=0,f=1;char......
  • Codeforces 1862G 题解
    传送门题解因为有这个操作:将序列\(a\)加上\(\{n,n-1,\cdots,1\}\),考虑差分。那么显然每次操作会将差分数组中的每个元素减去\(1\),如果差分数组中有\(0\),就会把\(0\)删除。所以可以发现差分数组中剩下的一定是操作前的最大值。由于操作后最大值还是最大值,最小值仍......
  • CF1777A题解
    分析发现操作2不会改变数的奇偶性,故无视。那么操作就是单纯删一个数。对于一个连续出现\(x\)个奇偶性相同的数的序列,需要删\(x-1\)个数(因为只剩下一个数就不会和相邻的数奇偶性相同了)。觉得找序列太麻烦,观察到连续出现\(x\)个奇偶性相同的数的序列有\(x-1\)个不......
  • CF1523D Love-Hate 题解
    抽象化题意:一共有\(m\)个元素,给定\(n\)个集合,每个集合的元素不超过\(15\)个,求出一个元素个数最多的集合\(S\)是至少\(\lceil\dfrac{n}{2}\rceil\)个集合的子集。其中$p$$(1\len\le2\cdot10^5,1\lep\lem\le60)$我们先假设\(limit=\lceil\dfrac......
  • 2023级HAUT新生周赛题解汇总
    2023级HAUT新生周赛(零)熟悉周赛规则专场:2023级HAUT新生周赛(一)@21级学长专场(张子豪,张鑫,李昊阳):2023级HAUT新生周赛(二)@曹瑞峰专场:2023级HAUT新生周赛(三)@22级学姐专场(杨焱,刘振歌,周欣滢):2023级HAUT新生周赛(四)@牛浩然专场:2023级HAUT新生周赛(五)@陈兰锴专场:......
  • JWT Tool:针对 JSON Web Tokens 的测试工具题解JWT cracking
    什么是JWT?JWT是JSONWebToken的缩写,它是一串带有声明信息的字符串,由服务端使用加密算法对信息签名,以保证其完整性和不可伪造性。Token里可以包含所有必要的信息,这样服务端就无需保存任何关于用户或会话的信息了。JWT可用于身份认证,会话状态维持以及信息交换等任务。JWT由三部分......
  • CSP20230917-3 梯度求解 题解
    〇、题目太长了懒得写。简单来说就是求对于一个后缀表达式,每个询问给出一个下标和一些值,求以该下标变量为自变量其它变量为常数时的偏导数。一、思路考虑直接对于表达式建出表达式树。建树的过程比较直接:每次栈里面放节点编号,遇到符号就取出当前栈顶两个节点作为子节点。每......
  • Codeforces Round 886 (Div. 4) 题解
    link我为什么还要vpdiv4场。。。A直接找最大的两个判断一下。voidsolve(){ inta[3]; cin>>a[0]>>a[1]>>a[2]; sort(a,a+3); if(a[2]+a[1]>=10)cout<<"YES\n"; elsecout<<"NO\n";}B按照题目意思模拟。voidsolv......
  • P3657 题解
    是不是有点恶意评分了题目链接Sol看完题目就想到了这个题。这道题同样是求线段,不过这个加了点限制,发现一个点最多连4条边出去,暴力连边的复杂度是正确的,于是就把这题变成黄了。利用刚刚那道题的trick,把边按左端点排序后右端点的LIS就是答案。这里给一个更方便的做法,不用......