2026-10-25 hetao1733837 的刷题记录

LGP17706 ICPC 2019 Nanjing R Prince and Princess

原题链接:ICPC 2019 Nanjing R Prince and Princess

分析

当然了,如果说没有任何的反对者或者漠不关心者,那么,显然可以通过一次询问直接得出答案。


那么,如果说只存在反对者,结果同理,王子需要询问......好像没有这个数据范围......


难道说只有只存在支持者的时候才能行吗?这并不对......

说实在地,我觉得应该只进行第三个询问......

那么,会出现什么情况呢?

似乎只有成环的时候无法确定......

为啥 tag 是 greedy?

那么,不如进行雷霆大分讨!

那是啥啊😭


居然被我猜对了,但是,没有猜全......

确实,我们发现只进行第三个询问是非常优秀的,然后,我们最多使用 ( b + c ) × 2 + 1 (b+c)\times 2+1 (b+c)×2+1 次询问即可 。

相当于说把中立者当成反对者,在最劣的情况下,我们需要 b + c + 1 b+c+1 b+c+1 次才能发现谎言,剩下的全都是支持者,所以,需要 ( b + c ) × 2 + 1 (b+c)\times 2+1 (b+c)×2+1 次询问。

正解

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
int a, b, c;
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin >> a >> b >> c;
    if (a == 1 && b == 0 && c == 0){
        cout << "YES" << '\n';
        cout << 0;
        return 0;
    }
    if (a > b + c){
        cout << "YES" << '\n';
        cout << (b + c) * 2 + 1;
        return 0;
    }
    else{
        cout << "NO";
    }
}

LGP17784 山田凉不是罪过

原题链接:山田凉不是罪过

分析

思考一下,那么,对于单个测试点分数较高的,我们尽可能使得其包含的任务数量尽可能少......然后,还需要满足一共有 n n n 个测试点......思考一下......

别急,这个怎么那么像什么性价比贪心之类的东西......


题目转化为:构造一个数组 b b b,使得 ∑ i = 1 k b i = n \sum\limits_{i=1}^{k}b_i=n i=1∑kbi=n,且 ∑ i = 1 k a i 2 b i \sum\limits_{i=1}^{k}{\dfrac{a_i}{2^{b_i}}} i=1∑k2biai 取到最大值。呃,可能这个式子有点糙,是错的,但是,不要紧。

那岂不是将 a a a 进行降序排序,前面的都只给一个,最后一个给全?真的假的?

正解

cpp 复制代码
#include <bits/stdc++.h>
#define int long long
#define mod 998244353
using namespace std;
const int N = 1000005;
int n, k, a[N];
int qpow(int a, int b){
	int res = 1;
	while (b){
		if (b & 1)
			res = res * a % mod;
		a = a * a % mod;
		b >>= 1;
	}
	return res;
}
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> k;
	int mn = 0x3f3f3f3f, pos = 0;
	for (int i = 1; i <= k; i++){
		cin >> a[i];
		if (a[i] < mn){
			mn = a[i];
			pos = i;
		}
	} 
	sort(a + 1, a + k + 1, greater<int>());
	int ans = 0;
	for (int i = 1; i < k; i++){
		ans = (ans + a[i] * qpow(2, mod - 2)) % mod;
	}
	int tmp = qpow(2, (n - k + 1));
	ans = (ans + a[k] * qpow(tmp, mod - 2)) % mod;
	cout << ans << "\n";
	for (int i = 1; i <= k; i++){
		if (i == pos){
			cout << n - k + 1 << " ";
		}
		else{
			cout << 1 << " ";
		}
	}
}

LGP17678 IO 2025 #4 拆钞幻术

原题链接:IO 2025 #4 拆钞幻术

分析

有解和无解是容易判定的,就是我们对比一下和的大小即可,这个前缀和还挺好做的......

然后,我们要思考最小的特效费用......难不成从大到小直接每次整出来一点就行?居然被我猜对了......

那么,思考一下,这就需要我们快速地排序并统计了......然而,这个并不容易快速统计......呃......别搞啊,黄题这样吗😭

我会做 O ( q n l o g n ) O(qnlogn) O(qnlogn) 之类的东西,但是,题目明显让我做 O ( q l o g n ) O(qlogn) O(qlogn) 之类的东西......

不是,那我咋才能做到啊?不是,我统计至少也是 O ( q n ) O(qn) O(qn) 的啊?

我们发现,我们每次的答案是(先默认 a a a 在 l , r l,r l,r 上有序):

∑ i = l r ( S − ∑ j = l i − 1 a j ) × a i \sum\limits_{i=l}^{r}{(S-\sum\limits_{j=l}^{i-1}{a_j})\times a_i} i=l∑r(S−j=l∑i−1aj)×ai

后面的还好说,我怎么保证其有序呢?怎么快速求解呢?

难不成要离线?


什么叫离线+线段树?这是黄?

哦不不不,我们发现 ,在我们证明的时候,可以写出式子:

S 2 − ∑ a i 2 2 \dfrac{S^2-\sum\limits_{}^{}{a_i^2}}{2} 2S2−∑ai2

那么,我们要使得后面尽可能大,所以,倒叙排序是对的。那么,对于一段区间,直接减着做就行。

正解

cpp 复制代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 200005;
int n, q, x[N];
int sum1[N], sum2[N];
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> q;
	for (int i = 1; i <= n; i++){
		cin >> x[i];
		sum1[i] = sum1[i - 1] + x[i];
		sum2[i] = sum2[i - 1] + x[i] * x[i];
	}
	for (int cs = 1, l, r, S; cs <= q; cs++){
		cin >> l >> r >> S;
		int tmp = sum1[r] - sum1[l - 1];
        if (S < tmp)
            cout << -1 << "\n";
        else
    		cout << (2 * S * tmp - tmp * tmp - sum2[r] + sum2[l - 1]) / 2 << "\n";
	}
}

LGP17677 IO 2025 #4 现在你看见我了

原题链接:IO 2025 #4 现在你看见我了

分析

我发现,我们似乎统计出现过最少的字符,然后,直接加 1 1 1 输出就行?


好久没有量化直觉了......思考一下我是怎么想到的......我感觉......

为啥不过啊???


哦,对于一段,只要他没有出现一些字符,则可以添加上来使得不是子串......为什么那么奇怪呢......

哦哦哦,就是说,一旦一个区间有未出现的,那么,不管他,但是,一旦有一个所有都出现的,那么,可以将其"缩起来"?然后,总长度加一下就行了......


所以,这个究竟在贪心什么?!?极大匹配!?

正解

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
int n;
string s;
int cnt[26];
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n;
	cin >> s;
	int ans = 0;
	for (int i = 0; i < (int)s.length(); i++){
		cnt[s[i] - 'a']++;
		bool flag = true;
		for (int j = 0; j < n; j++){
			if (cnt[j] == 0){
				flag = false;
				break;
			}
		}
		if (flag){
			ans++;
			memset(cnt, 0, sizeof(cnt));
		}
	}
	cout << ans + 1;
}

LGP17584 【LABOI-R1】过客 / guest

原题链接:【LABOI-R1】过客 / guest

分析

呃......曼哈顿距离是个什么来着......我是说他的图形......哦,是一个以 ( x , y ) (x,y) (x,y) 为对角线交点的倾斜 π 4 \dfrac{\pi}{4} 4π 的的正方形......

首先,这个小 Z Z Z 必须到达这个正方形里面,然后,在这个正方形里往返移动即可。而且,每次他移动的距离都是 1 1 1,相对可靠一点吧。

那么,可以知道的是,对于 k = 0 k=0 k=0,我们一方面求出到达该点的距离,然后对于剩下的步数我们需要除以 2 2 2;剩下的,我们需要知道的是,我们至少走多少步可以到达正方形里面。

我们假设一个点 ( x + a , y + k − a ) (x+a,y+k-a) (x+a,y+k−a),求 ∣ s − x − a ∣ + ∣ t − y − k + a ∣ |s-x-a|+|t-y-k+a| ∣s−x−a∣+∣t−y−k+a∣ 的最小值......按照之前的经验,我们可以过 ( s , t ) (s,t) (s,t) 做一条与正方形某条边平行的线,发现,走到正方形一个顶点,当然,如果可以,直接走到边上似乎也不赖......总之分讨一下吧......


好吧,有点小问题......

正解

cpp 复制代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
int q;
int x, y, s, t, k, l;
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> q;
	for (int cs = 1; cs <= q; cs++){
		cin >> x >> y >> s >> t >> k >> l;
		int d = abs(x - s) + abs(y - t);
		int ans = 0;
		if (k == 0){
			if (s == x && t == y){
				ans = l / 2;
			}
			else{
				if (l >= d){
					ans = 1 + (l - d) / 2;
				}
			}
		}
		else{
			if (d <= k){
				ans = l;
			}
			else{
				ans = l - (d - k) + 1;
			}
		}
		cout << max(ans, 0ll) << "\n";
	} 
}

LGP17511 入门赛 #52 月饼调配

原题链接:入门赛 #52 月饼调配

分析

刚才使用 AI 把之前的哪个结构体给调过去了,呃,感觉对我的帮助并不大......场上要真的碰到了怎么办啊😭


贪心地写,多了就拿走,少了就往里面拿......呃......具体地,我们从叶子开始考虑,把多的给他的父亲,如果少了,就找父亲要,然后动态的加减,应该也不会很慢。每次尽可能地使用通道......这个实现的难度主要在代码吧......

啊?好像并不是特别困难?

正解

cpp 复制代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 200005;
int n;
int s[N], t[N];
vector<pair<int, int>> e[N];
int val[N];
int ans = 0;
void dfs(int u, int fa){
	for (auto tmp : e[u]){
		if (tmp.first == fa)
			continue;
		dfs(tmp.first, u);
		val[u] += val[tmp.first];
		ans += (abs(val[tmp.first]) + tmp.second - 1) / tmp.second;
	}
}
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n;
	for (int i = 1; i <= n; i++){
		cin >> s[i];
	}
	for (int i = 1; i <= n; i++){
		cin >> t[i];
		val[i] = s[i] - t[i];
	}
	for (int i = 1, u, v, c; i < n; i++){
		cin >> u >> v >> c;
		e[u].push_back({v, c});
		e[v].push_back({u, c});
	}
	dfs(1, 0);
	cout << ans;
}

LGP5690 CSP-S 2019 江西 日期

原题链接:CSP-S 2019 江西 日期

分析

爆搜居然写挂了😭

正解

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
string s, t;
int ans = 6;
int a[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
void dfs(int p, int res){
	if (p == 5){
		int mo = (s[0] - '0') * 10 + (s[1] - '0');
		int dy = (s[3] - '0') * 10 + (s[4] - '0');
		if (mo <= 0 || mo > 12)
			return ;
		if (dy <= 0 || dy > a[mo])
			return ;
		ans = min(ans, res);
		return ;
	}
    if (p == 2){
        dfs(p + 1, res);
    }
    else{
        for (int i = 0; i <= 9; i++){
		    s[p] = (char)(i + '0');
    		if (s[p] != t[p])
    			dfs(p + 1, res + 1);
    		else
    			dfs(p + 1, res);
	    }
    }
}
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> t;
	s = t;
	dfs(0, 0);
	cout << ans;
} 

LGP14402 JOISC 2016 危险的滑冰 / Dangerous Skating

原题链接:JOISC 2016 危险的滑冰 / Dangerous Skating

分析

这个给出了 O ( n 2 ) O(n^2) O(n2) 甚至 O ( n 2 l o g n ) O(n^2logn) O(n2logn) 的可能......

难道说我可以建图吗?但是,怎么控制每次新加入一块冰呢?

怎么建图呢?我觉得我们需要用一些贪心的思想了......


首先,我们肯定要清理一些"杂兵",我们把那些不连通的、位置重合的直接特判掉。

然后,思考建图......

可以这样建图吗?就是说,对于一个位置,其四周最近的冰块,我们将两者距离设为边权即可连边......然后跑最短路......似乎就做完了?那么,我们还是没有把启点变成冰块考虑进去,但是,我们发现,每次反弹,都需要 2 2 2 的代价,这个真实太妙了!就是说,我们过去一趟,回来一趟,恰好是"反弹",然后,似乎是做完了?我不知道......可能吧......好吧......


看一下具体怎么实现......

话说回来,我去年为什么不写呢?这个去年不会是个紫吧......哦......去年我是不是想把主页的颜色调成紫色所以不写蓝题?我咋这么幼稚呢?

正解

cpp 复制代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1005;
int r, c;
int r1, c1;
int r2, c2;
char ch[N][N];
int L[N * N], R[N * N], T[N * N], D[N * N];
int dis[N * N];
vector<pair<int, int>> e[N * N];
void dijkstra(int S){
	memset(dis, 0x3f, sizeof(dis));
	priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q;
	dis[S] = 0;
	q.push({0, S});
	while (!q.empty()){
		auto tmp1 = q.top();
		q.pop();
		for (auto tmp2 : e[tmp1.second]){
			if (dis[tmp2.first] > dis[tmp1.second] + tmp2.second){
				dis[tmp2.first] = dis[tmp1.second] + tmp2.second;
				q.push({dis[tmp2.first], tmp2.first});
			}
		}
	} 
}
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> r >> c;
	for (int i = 1; i <= r; i++){
		for (int j = 1; j <= c; j++){
			cin >> ch[i][j];
		}
	}
	cin >> r1 >> c1;
	cin >> r2 >> c2;
	int lst = 0;
	for (int i = 1; i <= r; i++){
		for (int j = 1; j <= c; j++){
			if (ch[i][j] == '#'){
				lst = j;
			}
			else{
				L[(i - 1) * c + j] = (i - 1) * c + lst + 1;
			}
		}
	}
	lst = 0;
	for (int i = 1; i <= r; i++){
		for (int j = c; j >= 1; j--){
			if (ch[i][j] == '#'){
				lst = j;
			}
			else{
				R[(i - 1) * c + j] = (i - 1) * c + lst - 1;
			}
		}
	}
	lst = 0;
	for (int i = 1; i <= c; i++){
		for (int j = 1; j <= r; j++){
			if (ch[j][i] == '#'){
				lst = j;
			}
			else{
				T[(j - 1) * c + i] = lst * c + i; 
			} 
		}
	}
	lst = 0;
	for (int i = 1; i <= c; i++){
		for (int j = r; j >= 1; j--){
			if (ch[j][i] == '#'){
				lst = j;
			}
			else{
				D[(j - 1) * c + i] = (lst - 2) * c + i; 
			} 
		}
	}
	for (int i = 1; i <= r; i++){
		for (int j = 1; j <= c; j++){
			int pos = (i - 1) * c + j;
			if (ch[i][j] == '#')
				continue;
			if (ch[i - 1][j] == '.')
				e[pos].push_back({(i - 1 - 1) * c + j, 2});
			if (ch[i + 1][j] == '.')
				e[pos].push_back({(i - 1 + 1) * c + j, 2});
			if (ch[i][j - 1] == '.')
				e[pos].push_back({(i - 1) * c + j - 1, 2});
			if (ch[i][j + 1] == '.')
				e[pos].push_back({(i - 1) * c + j + 1, 2});
			e[pos].push_back({L[pos], 1});
			e[pos].push_back({R[pos], 1});
			e[pos].push_back({T[pos], 1});
			e[pos].push_back({D[pos], 1});
		}
	}
	dijkstra((r1 - 1) * c + c1);
	if (dis[(r2 - 1) * c + c2] == 0x3f3f3f3f3f3f3f3f)
		cout << -1;
	else
		cout << dis[(r2 - 1) * c + c2];
}
相关推荐
Jsundoku2 小时前
第七章 机器学习 -- 其他经典算法
人工智能·算法·机器学习
fqbqrr2 小时前
2610C++,UI复合技术在窗口中绘画字体图标
c++·ui
进击的丸子2 小时前
基于 ArcFace SDK 的跨平台人脸特征值下发、同步以及存储方案
后端·算法·代码规范
见叶之秋2 小时前
【C++】红与黑的边界:红黑树从插入到自检
数据结构·c++·算法·面试
程序猿编码2 小时前
不依赖 vLLM/llama.cpp:一套面向学习的 DeepSeek-R1 CUDA 推理实现
c++·学习·语言模型·llama·vllm·大模型推理
kiracrimson3 小时前
string 容器:从 C 字符串到会自己扩容的类
开发语言·数据结构·c++·stl
程序猿编码3 小时前
纯 C++ 手写 LLM 推理引擎:分页 KV 缓存、连续批、多卡张量并行全部内置
c++·深度学习·缓存·大模型推理·自动微分·模型推理
一条闲鱼_mytube3 小时前
分布式 ID 生成方案:雪花算法与号段模式
分布式·算法·wpf
Msir_Modern3 小时前
Noita 元胞沙盒笔记
算法·unity·c#·游戏引擎·元胞自动机