VP Codeforces Round 908 (Div. 2)


A - Secret Sport

题意:两个人比赛,每有一个人赢了\(X\)场就算它赢了一轮。比赛是在有一个人赢了\(Y\)轮后结束。你不知道\(XY\),但给你一个每场的输赢情况,求谁是赢家。

去求\(XY\)非常难,不如倒着想,一轮必然是因为赢的那个人赢了一把而结束,同样,整个比赛也是因为赢的那个人赢了一轮而结束。所以,最后一个赢得人就是赢家。

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::string s;
    std::cin >> s;
    std::cout << s.back() << "\n";
}

B. Two Out of Three

题意:题意,给你一个\(a\),你要构造一个\(b\)使得正好满足三个条件其中得任意两个。

  1. 有一个 \(1 \leq i, j \leq n\) 使得 \(a_i = a_j\), \(b_i = 1\), \(b_j = 2\).
  2. 有一个 \(1 \leq i, j \leq n\) 使得 \(a_i = a_j\), \(b_i = 1\), \(b_j = 3\).
  3. 有一个 \(1 \leq i, j \leq n\) 使得 \(a_i = a_j\), \(b_i = 2\), \(b_j = 3\).

对于每一类数,他们只能有两个不同的值,否则就会同时满足三个条件。那么让每个个数大于等于\(2\)的数字满足一个条件,只需要两类数就可以满足两个条件,其他的全部赋值为\(1\)就行。

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::vector<int> a(n);
    for (int i = 0; i < n; ++ i) {
    	std::cin >> a[i];
    }

    std::map<int, std::vector<int> > mp;
    for (int i = 0; i < n; ++ i) {
    	mp[a[i]].push_back(i);
    }

    std::vector<int> b(n, 1);
    int cnt = 0;
    for (auto & [x, a] : mp) {
    	if (a.size() >= 2) {
    		if (cnt == 0) {
	    		b[a[1]] = 2;
    		} else if (cnt == 1) {
    			b[a[1]] = 3;
    		}
    		++ cnt;
    	} 
    }

    if (cnt < 2) {
    	std::cout << -1 << "\n";
    } else {
    	for (int i = 0; i < n; ++ i) {
    		std::cout << b[i] << " \n"[i == n - 1];
    	}
    }
}	

C. Anonymous Informant

题意:如果\(a_i = i\),则可以让\(a\)左移\(i\)次。现在给你一个数组\(b\),说他是由某个数组进行\(k\)次操作变过来的,判断对错。

模拟一下发现,因为\(a_i = i\),那么左移\(i\)次后\(a_i\)到了结尾。因为\(b\)是变过来的,那么它的最后一个数就代表上一次左移了几位,那我们可以不断右移反着回去,如果某一次出现操作的数大于\(n\),则无解。如果有一个位置出现两次,说明有环,我们在环上必然可以选一个起点使得它操作\(k\)次变成\(b\)。我们模拟\(\min(n, k)\)次即可。因为\(n\)次必然会出现一个环,否则我们\(k < n\)并且可以操作\(n\)次以上,一定有一个数组可以通过\(k\)次操作到\(b\)

点击查看代码
void solve() {
	int n, k;
	std::cin >> n >> k;
	std::vector<int> a(n);
	for (int i = 0; i < n; ++ i) {
		std::cin >> a[i];
	}

	int x = 0;
	std::vector<int> st(n);
	st[0] = 1;
	for (int i = 0; i < std::min(n, k); ++ i) {
		if (a[n - 1 - x] > n) {
			std::cout << "NO\n";
			return;
		}

		x += a[n - 1 - x];
		x %= n;
		if (st[x]) {
			std::cout << "YES\n";
			return;
		}

		st[x] = 1;
	}

	std::cout << "YES" << "\n";
}

D. Neutral Tonality

做过最简单的\(d\)

题意:给你两个数组\(a, b\),你要把\(b\)的每个数插到\(a\)的任意一个位置,让最后数组的最长子序列长度最短。

如果\(a_i > a_{i+1}\),那么我们是不是可以把\([a_{i+1}, a_i]\)的数都插到中间,这样不会使\(LIS\)变长。然后发现,好像就做完了。

点击查看代码
void solve() {
    int n, m;
    std::cin >> n >> m;
    std::vector<int> a(n), b(m);
    for (int i = 0; i < n; ++ i) {
    	std::cin >> a[i];
    }

    for (int i = 0; i < m; ++ i) {
    	std::cin >> b[i];
    }

    
    std::vector<int> ans;
	std::sort(b.begin(), b.end(), std::greater<int>());
	int j = 0;
	for (int i = 0; i < n; ++ i) {
		while (j < m && b[j] >= a[i]) {
			ans.push_back(b[j ++ ]);
		}

		ans.push_back(a[i]);
	}

	while (j < m) {
		ans.push_back(b[j ++ ]);
	}

    for (int i = 0; i < n + m; ++ i) {
    	std::cout << ans[i] << " \n"[i == n + m - 1];
    }
}

E. Freedom of Choice

题意:\(m\)个多重集,第\(i\)个多重集有\(n_i\)个数,每个数有\(c_i\)个。你要从每个集合里选数,选的个数在\([l_i, r_i]\)之间。定义集合的价值为在集合内且等于集合元素个数的元素数量。

我们可以枚举选\(i\)数,那么尽量不要选\(i\)这个数字。每个数字模拟一下取最小值就行。

点击查看代码
void solve() {
    int m;
    std::cin >> m;
    std::map<i64, std::vector<std::pair<int, i64> > > mp;
    std::vector<std::array<i64, 4> > a(m);
    i64 suml = 0, sumr = 0;
    for (int i = 0; i < m; ++ i) {
    	i64 n, l, r;
    	std::cin >> n >> l >> r;
    	suml += l, sumr += r;
    	std::vector<i64> b(n), c(n);
    	for (int j = 0; j < n; ++ j) {
    		std::cin >> b[j];
    	}

    	for (int j = 0; j < n; ++ j) {
    		std::cin >> c[j];
    	}

    	i64 tot = 0;
    	for (int j = 0; j < n; ++ j) {
    		mp[b[j]].push_back({i, c[j]});
    		tot += c[j];
    	}
    	a[i] = {n, l, r, tot};
    }

    for (i64 i = suml; i <= sumr; ++ i) {
    	if (!mp.count(i)) {
    		std::cout << 0 << "\n";
    		return;
    	}
    }

    i64 ans = 1e18;
    for (i64 i = suml; i <= sumr; ++ i) {
    	i64 sum = sumr, res = 0;
    	for (auto & [id, cnt] : mp[i]) {
    		auto & [n, l, r, tot] = a[id];
    		sum -= r;
    		if (tot - cnt < l) {
    			res += l - (tot - cnt);
    			sum += l;
    		} else {
    			sum += std::min(r, tot - cnt);
    		}
    	}

    	res += std::max(0ll, i - sum);
    	ans = std::min(ans, res);
    }

    std::cout << ans << "\n";
}
posted @ 2025-01-24 22:00  maburb  阅读(37)  评论(0)    收藏  举报