当前位置: 首页 > news >正文

[Informatics] (Legacy) CodeForces + Atcoder 问题几则

发布这篇文章时本人已退役,内容撰写于几年前,这里挑了写的比较好的几个题出来,作为留念和参考。

Problem 0

Source: AT_arc173_c - Not Median

简单一点讲一下吧。

观察到答案会有很多 \(3\)\(5\) 之类的小数,因此构造一个具有巨大答案的数列:\(\{-a,a,-b,b,0,-c,c,-d,d\}\)(相对大小)。

尽管我们要计算出 \(0\) 处的答案需要扫过大量的元素,但是手玩一下这个数列,可以发现:非边界元素都可以确定对应答案为 \(\bm 3\)

于是我们就可以在扫的过程当中确定哪些点的答案肯定是 \(3\),不用再次计算。这样就可以做到均摊 \(\mathcal {O(n)}\)

实际上实现会有一些麻烦。会有几种情况停止扫描:

  1. 在当前元素的左面 / 右面连着出现两个符号相同的。
  2. 关于当前元素对称的两个位置上元素符号相同。

注意优先级。条件 \(1\) 的长度更短,所以优先判断条件 \(1\)。至于左右没有优先级。

但是条件 \(1\) 有一个 Corner Case:假如截下来长度不是奇数,就只能往反方向借一个。但是对于数列首尾,就没法借了,所以只能暴力算首尾位置的答案。

注意:如果这里能借一个,就保证满足条件。如果不满足早就在之前被判掉了。

细节大概就这么多。如果你担心填 \(3\) 填的太多了少填两三个爆算也行。

这就做完了。AC Code。

Problem 1

Source: CF1762D GCD Queries

下面简称 \(\gcd(p_i,p_j)\)\(\text{z}(i,j)\)

这个限制看起来就像每两步询问就可以检验一个数是否为 \(0\),或者直接判断其不为 \(0\)。但是直接下手有些困难,我们显然需要找到一些性质。

考虑到对于一个排列中元素都不相同,根据这个性质,如果 \(p_i=0\),那么一定满足 \(\text{z}(i,j)\not =\text{z}(i,k)\),反过来 \(p_i\not =0\) 的充分条件是 \(\text{z}(i,j) = \text{z}(i,k)\)

这一条看起来很有用,但是过于狭隘,不一定存在 \(\text{z}(i,j)=\text{z}(i,k)\),而这又不是必要条件。考虑到这种情况已经需要询问 \(2\) 次,我们不妨继续在 \(\text{z}(i,j)\)\(\text{z}(i,k)\) 的大小关系上做文章。

于是考虑 \(\text{z}(i,j)\not =\text{z}(i,k)\),此时发现没法判定 \(p_i\),但是当 \(p_i=0\) 的时候肯定 \(j,k\) 都不为 \(0\),如果 \(p_i \not = 0\) 的时候就说明 \(\text{z}(i,j)\)\(\text{z}(i,k)\)\(p_i\) 的两个不同的因数。

不妨设 \(\text{z}(i,j)<\text{z}(i,k)\),那么即使最劣情况下 \(\text{z}(i,k)=p_i\),无法判定 \(p_k\),也可以判定 \(p_j\),因为 \(\gcd(p_j,p_i)\not= p_i\not=\gcd(p_i,0)\),所以 \(p_j\not=0\)

在以上观察之后我们发现,任意的询问 \(\text{z}(a,b)\)\(\text{z}(a,c)\) 都可以对满足 \(x\in\{a,b,c\}\)\(x\) 进行判定其 \(p_x\not=0\)。于是我们发现只需要判定 \(n-2\) 次就一定可以得到可能为 \(0\) 的两个元素。

Implementation

#include <bits/stdc++.h>
using namespace std;
int solve();
signed main() { int t; cin >> t; while (t--) solve(); return 0; }
int _gcd(int x, int y) { cout << "? " << x << " " << y << endl;int r; cin >> r; return r;
}
int f(int i, int j, int k) {int A = _gcd(i, k), B = _gcd(j, k);if(A == B) return k;if(A < B) return i;return j;
}
int solve() {int n;cin >> n;if(n == 2) {puts("! 1 2"); int x; cin >> x;return 0;}priority_queue<int> q;for(int i = 1; i <= n; i++) q.push(i);while(q.size() != 2) {int x = q.top(); q.pop();int y = q.top(); q.pop();int z = q.top(); q.pop();int w = f(x, y, z);if(x != w) q.push(x);if(y != w) q.push(y);if(z != w) q.push(z);}cout << "! " << q.top() << ' ';q.pop();cout << q.top() << endl;int x; cin >> x;if(x == -1) return puts("WA");//This line will be never executed.return 0;
}

时间复杂度 \(\mathcal O(n\log n)\),理论可 \(\mathcal O(n)\)

Problem 2

Source: CF1715F Crop Squares

这篇解答采用 CF Hint 式的解答,应该更有启发性

1

考虑像下图一样构造多边形:

2

Hint 1,对于答案的 \(y\) 值和重叠面积 \(s_0\),有一定的函数关系,一个 \(y\) 对应一个 \(s_0\),一个 \(s_0\) 对应一个 \(y\)

换言之,同一 \(y\) 值得到的重叠面积相同,同一重叠面积得到的 \(y\) 值相同,

3

容易得到,重叠面积是一个 \(\frac{y}{m}\times 1\) 的矩形加上一个 \(\frac{1}{m}\times1\) 的直角三角形,即,\(s_0=\frac{y+0.5}{m}\),稍微变化下形式即可得到 \(y=s_0m-0.5\)

证明略,运用相似即可。

4

同理的锯齿状,横着询问,对于重叠面积 \(s_1\) 同理得到 \(x=s_1n-0.5\)

这样,在两次询问内,我们就得到了答案的 \(x,y\)

5

注意到这样的锯齿状不被认为是封闭的多边形,所以我们可以将这些点稍微下调 \(10^{-7}\) 个单位长度即可:

如图,橙色的点下调即可。(横式同理)

Implementation

对于 C++ 语言,cout << endl 会自动刷新缓存,所以可以不使用 cout << flush

本题的询问次数很少,所以你刷不刷新都没关系。

AC link

void query(int x, int y, long double &d, bool opt) {printf("? %d\n", 2 * x + 2);for(int i = 0; i < x; i++) {int tx = i, ty = 0, ttx = i, tty = y;if(opt) {printf("%d %d\n", ty, tx);printf("%d %d.99999999\n", tty, ttx);}else {printf("%d %d\n", tx, ty);printf("%d.99999999 %d\n", ttx, tty);}}if(opt) printf("%d %d\n%d %d\n", y, x, y, 0);else printf("%d %d\n%d %d\n", x, y, 0, y);cin >> d;return ;
}
signed main()
{int n, m;scanf("%d %d", &n, &m);long double s0, s1;query(n, m, s0, 0);query(m, n, s1, 1);printf("! %.8Lf %.8Lf\n", s1 * n - 0.5, s0 * m - 0.5);return 0;
}

Problem 3

Source: CF1421E - Swedish Heroes

有点观察但是绝对没有 2k7 的题。我觉得这个最多 2k4。

首先想到区间 dp,数据范围暗示我们这不可行。

那怎么办。我们不难发现符号序列应该满足:

  • 存在两个连着的同号。
  • 设正号数量为 \(p\),则 \(n+p-2\)\(3\) 的倍数。

然后 \(dp[i][p \bmod 3][\text{last}][第一条满足]\) 就可以 \(\mathcal O(n)\) 算了。到这里我们就做完了,但是为什么这个结论是对的呢?

注:以下所提深度,满足根节点深度为 \(1\)

必要性:

首先我们可以把整个操作序列变成一棵二叉苹果树。某个节点深度的奇偶即决定了其最终正负。考虑二叉苹果树的性质,那么一定会存在至少一对相邻节点深度相同,其有同一个父亲。

其次就是 \((n+p)\bmod 3=2\) 的证明。我们考虑对于一个奇深度的节点,如果挂上两个儿子,那么会使得 \(n\gets n+1,p\gets p+2\),因此 \((n+p)\bmod 3\) 不变。如果对于一个偶深度的节点挂上两个儿子,那么会使得 \(n\gets n+1,p\gets p-1\),因此 \((n+p)\bmod 3\) 还是不变。考虑初始状态 \(n=p=1\),所以 \((n+p)\bmod 3=2\)

充分性:

即,为什么一定一个满足条件的符号序列一定可以还原成一个操作序列。

依旧是一棵二叉苹果树,这里我们就相当于一棵叶子节点深度奇偶性序列满足要求时一定还原出一棵二叉苹果树。

将所有连着的同号的节点给它们连上父亲。

这样,我们就得到了类似于这样的东西:

因为我们把能连的都连了,所以不会产生左右两个孤立点的深度奇偶性都和合并过一次的点的深度奇偶性相同,因为这种情况我们可以多合并一次。如图:

然后就回到了和初始问题一样的规模,并且在这样贪心的合并下,一定可以保证,永远存在两个连着的同号。我们依旧使用类似的处理方式,每次合并两个,根据上面提到的证明就一定不会产生深度冲突。

最后一个问题即,如果还原到根节点的时候深度为 \(0\),这种是没有可能的。一旦满足了 \(n+p-2\)\(3\) 的倍数,如果合并两个奇深度点,\(n\gets n-1,p\gets p-2\);如果合并两个偶深度点,\(n\gets n-1,p\gets p+1\),所以和模 \(3\) 不变,最终留下的一定是 \(n=p=1\),满足要求。

最后注意 \(n=1\) 特判,因为 \(n=1\) 不需要存在相邻两个同号的。

Code

http://www.jsqmd.com/news/363017/

相关文章:

  • 成都美术艺考集训机构优质推荐榜:美术艺考校考培训机构/美术艺考集训培训机构/美术艺考集训学校/专业美术艺考培训/选择指南 - 优质品牌商家
  • Java毕设选题推荐:基于springboot的在线社区系统的设计与开发基于Spring Boot的社区便民服务管理系统的设计与实现【附源码、mysql、文档、调试+代码讲解+全bao等】
  • 技术项目招人难、用人贵?唐普 IT 人力外包,帮企业破解人力卡点难题
  • BeeWorks企业通讯:赋能企业高效沟通,守护安全协同新生态
  • WordPress定制开发自动化测试最佳实践
  • 深入理解Redis哨兵(Sentinel)原理:高可用架构的核心守护者
  • 南昌瓷砖卫浴专业商家推荐榜:南昌卫浴浴室柜、南昌卫浴浴缸、南昌卫浴淋浴房、南昌卫浴花洒、南昌卫浴马桶、南昌卫浴龙头选择指南 - 优质品牌商家
  • 字节这款新AI让导演都慌了!Seedance2.0凭什么能自动剪大片?
  • 计算机Java毕设实战-基于springboot的在线社区系统的设计与开发基于SpringBoot的社区居民服务系统的设计与实现【完整源码+LW+部署说明+演示视频,全bao一条龙等】
  • 工厂产品良率低怎么办?关键在于制造过程
  • 代码是如何变成可执行文件的?
  • 深入解析:【C++】递归与迭代:两种编程范式的对比与实践
  • Ruby 模块(Module)
  • Day38-20260209
  • Memcached incr/decr 命令详解
  • 10.1 重大发现!消息可靠传输原来是这样保证的?
  • winget坏了修复
  • 在算法的茧房中悬鉴:养护人叙事环与“悟空悖论”的超越
  • 成都诚信艺考美术集训机构优质推荐 - 优质品牌商家
  • 三亚平价海鲜必看!2026年度高性价比湘菜排行榜推荐
  • 9.1 WebSocket网关架构设计竟然可以这样做?
  • 2026别墅电梯优质厂家推荐榜 - 优质品牌商家
  • 折叠面板(Accordion)
  • Pandas 简介
  • 当你 push 完分支,再提 MR 时,main 已经更新了,会发生什么?
  • 《Foundation 分页》
  • 2026年别墅电梯厂家推荐:老小区旧楼加装电梯多少钱一台/4层别墅电梯一般多少钱/六层旧楼加装电梯价格/选择指南 - 优质品牌商家
  • 智能医疗 | 算法稳定性在医疗设备中的重要性
  • Java毕设项目推荐-基于springboot的软件开发项目任务跟踪系统的设计与实现基于springboot的软件协作跟踪平台的设计与开发【附源码+文档,调试定制服务】
  • Scala 运算符