首页 > 其他分享 >[赛记] 多校A层冲刺NOIP2024模拟赛06

[赛记] 多校A层冲刺NOIP2024模拟赛06

时间:2024-10-13 09:10:16浏览次数:1  
标签:now 赛记 06 int tr 多校 mid include id

小 Z 的手套(gloves)100pts

最大值最小,考虑二分答案;

首先排序,然后每次找出数量较少的那个数组中的每个数 $ x $ 在另一个数组中有没有值在范围 $ [x - mid, x + mid] $ 的(其中 $ mid $ 为二分的答案),其实只需找 $ x - mid $ 就行,最后判断一下所有数是否合法即可;

因为已经升序排序,所以可以双指针维护,当然也可以 lower_bound,但是多个 $ \log $;

时间复杂度;$ \Theta(n \log Z) $ 到 $ \Theta(n \log Z \log n) $ 不等(其中 $ Z $ 为两个数组的极差);

点击查看代码
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
int n, m;
int a[500005], b[500005];
int vis[500005], vi[500005];
bool ck(int x) {
	for (int i = 1; i <= max(n, m); i++) {
		vis[i] = 0;
		vi[i] = 0;
	}
	if (n < m) {
		int now = lower_bound(b + 1, b + 1 + m, a[1] - x) - b;
		for (int i = 1; i <= n; i++) {
			int lpos = lower_bound(b + 1, b + 1 + m, a[i] - x) - b;
			if (lpos > m) return false;
			if (now < lpos) now = lpos;
			while(vis[now]) now++;
			vis[now] = i;
		}
		for (int i = 1; i <= m; i++) {
			if (vis[i]) {
				vi[vis[i]] = true;
				if (abs(a[vis[i]] - b[i]) > x) return false;
			}
		}
		for (int i = 1; i <= n; i++) if (!vi[i]) return false;
		return true;
	} else {
		int now = lower_bound(a + 1, a + 1 + n, b[1] - x) - a;
		for (int i = 1; i <= m; i++) {
			int lpos = lower_bound(a + 1, a + 1 + n, b[i] - x) - a;
			if (lpos > n) return false;
			if (now < lpos) now = lpos;
			while(vis[now]) now++;
			vis[now] = i;
		}
		for (int i = 1; i <= n; i++) {
			if (vis[i]) {
				vi[vis[i]] = true;
				if (abs(b[vis[i]] - a[i]) > x) return false;
			}
		}
		for (int i = 1; i <= m; i++) if (!vi[i]) return false;
		return true;
	}
}
int main() {
	freopen("gloves.in", "r", stdin);
	freopen("gloves.out", "w", stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
	}
	for (int i = 1; i <= m; i++) {
		cin >> b[i];
	}
	sort(a + 1, a + 1 + n);
	sort(b + 1, b + 1 + m);
	int l = 0;
	int r = 1000000000;
	int ans = 0;
	while(l <= r) {
		int mid = (l + r) >> 1;
		if (ck(mid)) {
			ans = mid;
			r = mid - 1;
		} else {
			l = mid + 1;
		}
	}
	cout << ans;
	return 0;
}

小 Z 的字符串(string)20pts

DP;

设 $ f_{i, j, k, 0/1/2} $ 表示现在选了 $ i $ 个 $ 0 $, $ j $ 个 $ 1 $ ,$ k $ 个 $ 2 $,当前是 $ 0/1/2 $ 的最小次数;

对于转移,发现肯定不会换同一个数,所以假设有转移 $ f_{i, j, k - 1, 0} \rightarrow f_{i, j, k, 2} $,我们只需将第 $ k $ 个数移动到当前位置 $ (i + j + k) $ 即可,然后计算贡献(注意绝对值),其它同理;

最后答案要除以 $ 2 $,因为假设有两个数能够被转移,它们两个的相对位置是不变的,也就是说前面的由后面的转移过来,后面的也由前面的转移过来,所以要除以 $ 2 $;

时间复杂度:$ \Theta(n^3) $;

点击查看代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
int n;
char s[505];
int t[3][405];
int f[205][205][205][3];
int c[3];
int main() {
	freopen("string.in", "r", stdin);
	freopen("string.out", "w", stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> (s + 1);
	n = strlen(s + 1);
	for (int i = 1; i <= n; i++) {
		t[s[i] - '0'][++c[s[i] - '0']] = i;
	}
	if (c[0] > (n + 1) / 2 || c[1] > (n + 1) / 2 || c[2] > (n + 1) / 2) {
		cout << -1;
		return 0;
	}
	memset(f, 0x3f, sizeof(f));
	f[0][0][0][0] = f[0][0][0][1] = f[0][0][0][2] = 0;
	for (int i = 0; i <= c[0]; i++) {
		for (int j = 0; j <= c[1]; j++) {
			for (int k = 0; k <= c[2]; k++) {
				int p = i + j + k;
				if (p == 0) continue;
				if (i) f[i][j][k][0] = min(f[i - 1][j][k][1], f[i - 1][j][k][2]) + abs(p - t[0][i]);
				if (j) f[i][j][k][1] = min(f[i][j - 1][k][0], f[i][j - 1][k][2]) + abs(p - t[1][j]);
				if (k) f[i][j][k][2] = min(f[i][j][k - 1][0], f[i][j][k - 1][1]) + abs(p - t[2][k]);
			}
		}
	}
	cout << min({f[c[0]][c[1]][c[2]][0], f[c[0]][c[1]][c[2]][1], f[c[0]][c[1]][c[2]][2]}) / 2;
	return 0;
}

一个真实的故事(truth)50pts

赛时打的 $ \Theta(\frac{nm \log^2 n}{w}) $ 结果算的时候少算俩 $ \log $,所以50pts;

正解就是线段树;

维护三个东西:

  1. 答案;

  2. 从左边开始的1 ~ k 出现的位置;

  3. 从右边开始的1 ~ k 出现的位置;

这样合并的时候只需将左区间的2和右区间的3合并起来,然后双指针扫一下即可;

时间复杂度:$ \Theta(nk \log n \log k) $,使用 $ sort $ 时可能会把后面的 $ \log $ 去掉;

点击查看代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int n, k, m;
int a[500005];
int cnt[35];
pair<int, int> rem[75];
int rcnt;
namespace SEG{
	inline int ls(int x) {
		return x << 1;
	}
	inline int rs(int x) {
		return x << 1 | 1;
	}
	struct sss{
		int l, r, ans, lb[35], rb[35];
	}tr[800005];
	inline void push_up(int id) {
		memset(cnt, 0, sizeof(cnt));
		rcnt = 0;
		for (int i = 1; i <= k; i++) {
			rem[++rcnt] = {tr[ls(id)].rb[i], i};
			rem[++rcnt] = {tr[rs(id)].lb[i], i};
		}
		sort(rem + 1, rem + 1 + rcnt);
		int now = 0;
		int an = 0x3f3f3f3f;
		int pos = 1;
		for (int i = 1; i <= rcnt; i++) {
			if (rem[i].first) {
				pos = i;
				break;
			}
		}
		int j = pos;
		for (int i = pos; i <= rcnt; i++) {
			if (!cnt[rem[i].second]) now++;
			cnt[rem[i].second]++;
			while(now == k) {
				an = min(an, rem[i].first - rem[j].first + 1);
				cnt[rem[j].second]--;
				if (cnt[rem[j].second] == 0) now--;
				j++;
			}
		}
		tr[id].ans = min({an, tr[ls(id)].ans, tr[rs(id)].ans});
		for (int i = 1; i <= k; i++) {
			if (tr[ls(id)].lb[i]) tr[id].lb[i] = tr[ls(id)].lb[i];
			else tr[id].lb[i] = tr[rs(id)].lb[i];
			if (tr[rs(id)].rb[i]) tr[id].rb[i] = tr[rs(id)].rb[i];
			else tr[id].rb[i] = tr[ls(id)].rb[i];
		}
	}
	void bt(int id, int l, int r) {
		tr[id].l = l;
		tr[id].r = r;
		tr[id].ans = 0x3f3f3f3f;
		if (l == r) {
			tr[id].lb[a[l]] = tr[id].rb[a[l]] = l;
			if (k == 1) {
				if (a[l] == k) tr[id].ans = 1;
			}
			return;
		}
		int mid = (l + r) >> 1;
		bt(ls(id), l, mid);
		bt(rs(id), mid + 1, r);
		push_up(id);
	}
	void add(int id, int pos, int x) {
		if (tr[id].l == tr[id].r) {
			tr[id].ans = 0x3f3f3f3f;
			if (k == 1) {
				if (a[tr[id].l] == k) tr[id].ans = 1;
			}
			tr[id].lb[x] = tr[id].rb[x] = 0;
			tr[id].lb[a[tr[id].l]] = tr[id].rb[a[tr[id].l]] = tr[id].l;
			return;
		}
		int mid = (tr[id].l + tr[id].r) >> 1;
		if (pos <= mid) add(ls(id), pos, x);
		else add(rs(id), pos, x);
		push_up(id);
	}
}
using namespace SEG;
int main() {
	freopen("truth.in", "r", stdin);
	freopen("truth.out", "w", stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> k >> m;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
	}
	bt(1, 1, n);
	int s, p, v;
	for (int i = 1; i <= m; i++) {
		cin >> s;
		if (s == 1) {
			cin >> p >> v;
			int x = a[p];
			a[p] = v;
			add(1, p, x);
		}
		if (s == 2) {
			if (tr[1].ans == 0x3f3f3f3f) cout << -1 << '\n';
			else cout << tr[1].ans << '\n';
		}
	}
	return 0;
}

标签:now,赛记,06,int,tr,多校,mid,include,id
From: https://www.cnblogs.com/PeppaEvenPig/p/18461882

相关文章

  • 多校A层冲刺NOIP2024模拟赛06
    多校A层冲刺NOIP2024模拟赛06\(T1\)A.小Z的手套(gloves)\(100pts/100pts\)容易发现将选出的左右手套各升序排序后,同一个位置上的两只手套的尺码差距一定在答案的候选集合里,画个数轴分讨一下就证完了。部分分\(20\%\):因为\(n=m\)所以不用管谁选谁不选的问题,故\(......
  • 多校 A 层冲刺 NOIP2024 模拟赛 06
    多校A层冲刺NOIP2024模拟赛06T小Z的手套(gloves)签到题答案显然具有单调性,排序后二分答案即可。T小Z的字符串(string)签到题注意到\(n\)较小,可以使用\(O(n^3)\)的算法,直接上大\(DP\)。设计状态\(f_{i,j,k,0/1/2}\)表示从左往右填到\(i\)位,已经填了\(j\)个\(0......
  • [赛记] 多校A层冲刺NOIP2024模拟赛05
    这场数数好数(number)100pts找三个数的和,而且允许$\Theta(n^2)$,那么我们可以维护出两个数的和,然后每次顺序遍历找这个数减去前面的某个数在任意两个数的和中有没有出现过,这个也是$\Theta(n^2)$的;所以时间复杂度:$\Theta(n^2)$,如果带$\log$会过不去,要用桶维护;点击......
  • 第106天:权限提升-WIN 系统&AD域控&NetLogon&ADCS&PAC&KDC&CVE 漏洞
    知识点1、WIN-域内用户到AD域控-CVE-2014-63242、WIN-域内用户到AD域控-CVE-2020-14723、WIN-域内用户到AD域控-CVE-2021-422874、WIN-域内用户到AD域控-CVE-2022-26923WIN-域控提权-CVE-2014-6324前提条件:1、需要域环境下一台主机普通用户账号密码2、一台主机的管理员权......
  • 多校A层冲刺NOIP2024模拟赛04
    02表示法直接递归即可,稍微写个高精。点击查看代码#include<bits/stdc++.h>usingnamespacestd;//#defineint__int128constintN=1e4;strings;intb[N],c[N],len;inta[N],tot;intread(){ intf=1,s=0;charch=getchar(); while(ch<'0'||ch>'9......
  • 多校A层冲刺NOIP2024模拟赛05
    好数(number没啥好说的直接\(O(n^2)\)枚举即可。点击查看代码#include<bits/stdc++.h>usingnamespacestd;constintN=2e6+107;constintd=2e5;intn,a[N],sum[N];intread(){ intf=1,s=0;charc=getchar(); while(c<'0'||c>'9'){if(c==�......
  • [46] (多校联训) A层冲刺NOIP2024模拟赛06
    HDK在与mt19937_64先生的石头剪刀布比赛中拿下十一连败的好成绩你也来试试吧#include<bits/stdc++.h>usingnamespacestd;#include"include/hdk/rand.h"usingnamespacehdk::Rand;chargetchar_(){charch=getchar();if(ch>='a'andch<='z......
  • 多校A层冲刺NOIP2024模拟赛06
    rank19,T1100pts,T230pts,T345pts,T420ptsT1小Z的手套(gloves)二分答案,贪心匹配\(O(n\logn)\)的check即可。时间复杂度\(O(n\log^2n)\)点此查看代码#include<bits/stdc++.h>#include<bits/extc++.h>//usingnamespace__gnu_pbds;//usingnamespace__gnu_cxx;usi......
  • ABB机器人备件3HAC035065-003
    ABB机器人备件3HAC035065-003是一款重要的伺服电机备件,对于确保ABB机器人的正常运行至关重要。以下是对该备件的详细解析:一、备件信息型号:3HAC035065-003类型:伺服电机备件适用品牌:ABB应用:主要用于ABB机器人的关节驱动,是机器人运动控制的关键部件。二、备件特点与优势高性能......
  • 2006-2023年上市公司社会责任报告、ESG报告文本(TXT)
    2006-2023年上市公司社会责任报告、ESG报告文本(TXT)1、时间:2006-2023年2、范围:A股上市公司3、样本量:14279份4、说明:上市公司社会责任报告是企业对外公布的一份关于其社会责任实践和成果的详细文件,涵盖环境保护、社会贡献和公司治理等方面的表现。通常包含公司在减少环境影响......