1.27 vp Codeforces Round #845 (Div. 2) and ByteRace 2023

A - Everybody Likes Good Arrays!

题意(构造)

给出序列a,需要使a中元素以相邻元素奇偶性不同排列,你可以进行若干操作:将一对相邻奇偶性相同的元素相乘
问最少需要多少次操作

思路

相当于消消乐,奇偶性相同的子序列一定只能保留一个,故观察什么时候奇偶性发生变化即可

void solve() {
	int n;
	cin >> n;
	vector<int> a(n + 1);
	for (int i = 1; i <= n; i ++) cin >> a[i];
	
	int t = a[1] & 1, cnt = 0;
	for (int i = 2; i <= n; i ++) {
		if (a[i] % 2 == t) cnt ++;
		else {
			t = t ^ 1;
		}
	}
	
	cout << cnt << endl;
}

\[\]

B - Emordnilap

题意(计数)

给出一个长度为n的排列,然后将其倒转接在后面,问按照这样规定的n!个排列会产生多少逆序对

思路

模拟几个数字后可知,对于一个含有n个元素的序列,所有含有n个元素的排列的逆序对数量都相等,故只需要求出其中一种排列的逆序数量然后乘n!即可
如:
序列123 会产生6种不同排列
我们只需观察123321这个序列会产生多少个逆序
序列:123321
贡献:012210
据观察可知逆序数量等于有n-1个元素首项为1,公差为1的等差数列和乘2

void solve() {
	int n;
	cin >> n;
	int x = (LL)n * (n - 1) % MOD;         //求出每种会产生多少个逆序
	for (int i = 1; i <= n; i ++) {        //乘以n!
		x = (LL)x * i % MOD;
	}
	
	cout << x << endl;
}

\[\]

C - Quiz Master

题意(排序+双指针)

给出n个数字,上限m
问从这个n个数字中能将1~m全部整除的一组数的极差最小值为多少

思路

先将n个数字排序,然后用双指针求出极差最小的满足条件的区间l,r

void solve() {
	int n, m;
	cin >> n >> m;
	vector<int> a(n + 1), cnt(m + 1, 0);              //cnt数组为记录1~m中每个因子在区间内的数量
	int num = 0;                                      //num为记录l,r区间包含多少个因子
	for (int i = 1; i <= n; i ++) cin >> a[i];
	sort(a.begin() + 1, a.end());
	
	auto ins = [&](int x) {                          //添加一个因子,若该因子数量恰好为一,则num加一
		if (x < 1 || x > m) return ;
		cnt[x] ++;
		if (cnt[x] == 1) num ++;
	};
	auto del = [&](int x) {                          //删除一个因子,若该因子数量恰好为零,则num减一
		if (x < 1 || x > m) return ;
		cnt[x] --;
		if (cnt[x] == 0) num --;
	};
	
	int l = 1, r = 0, ans = INF;
	
	for (int l = 1; l <= n; l ++) {                       //枚举l,求能满足条件的l,r区间
		while (num != m) {
			if (r == n) break;
			for (int i = 1; i <= sqrt(a[r + 1]); i ++) {
				if (a[r + 1] % i == 0) {
					ins(i);
					if (a[r + 1] / i != i) {
						ins(a[r + 1] / i);
					}
				}
			}
			r ++;
		}
		
		if (num == m) ans = min(a[r] - a[l], ans);
		
		for (int i = 1; i <= sqrt(a[l]); i ++) {
			if (a[l] % i == 0) {
				del(i);
				if (a[l] / i != i) del(a[l] / i);
			}
		}
	}
	
	if (ans == INF) cout << -1 << endl;
	else cout << ans <<endl;
}

总结:构造和计数类问题刷的比较多,反应较快。算法方面落后了。对于求类似极差的问题很容易可以想到区间,区间又可以想到双指针

posted @ 2023-01-27 11:24  nobodyL  阅读(35)  评论(0)    收藏  举报