AtCoder Beginner Contests 360~379

ABC360

E

题意

\(n-1\) 个白球和 \(1\) 个黑球。他们最初排成一行,黑球排在最左边。执行 \(k\) 次以下操作:

  • 随机选择 2 个 \(1\)\(n\) 之间的数,记为 \(a\)\(b\)。如果 \(a\not=b\),把左边的第 \(a\) 个球和第 \(b\) 个球交换。

\(k\) 次操作后,黑球排在从左数的第 \(x\) 个。求 \(x\) 的期望值 \(\text{mod}\ 998244353\)

分析

概率 DP。

\(f_i\)\(i\) 次操作后黑球位置的期望。每次操作有 \(n^2\) 种选数的方法,其中有 \((n-1)^2+1\) 种方法不会改变黑球的位置,有 \(2n-2\) 种方法会改变黑球的位置,且黑球位置改变到其他每个位置上的概率相等。故

\[\begin{aligned} f_i&=\dfrac{f_{i-1}((n-1)^2+1))}{n^2}+2(\sum\limits_{j=1}^{n}\dfrac{j}{n^2}-\dfrac{f_{i-1}}{n^2})\\ &=\dfrac{f_{i-1}(n^2-2n+2)}{n^2}+2\times\dfrac{\frac{n(n+1)}{2}-f_{i-1}}{n^2}\\ &=\dfrac{f_{i-1}(n^2-2n+2)}{n^2}+\dfrac{n+1}{n}-\dfrac{2f_{i-1}}{n^2}\\ &=\dfrac{f_{i-1}(n^2-2n)+n(n+1)}{n^2}\\ \end{aligned} \]

提交记录

F

题意

\(N\) 个区间 \([L_i,R_i]\)

定义满足 \(l_a<l_b<r_a<r_b\)\(l_b<l_a<r_b<r_a\) 的两个区间 \([l_a,r_a]\)\([l_b,r_b]\) 为交叉的。

定义 \(f(l,r)\)\(N\) 个区间中,与 \([l,r]\) 交叉的区间的个数。

请求出满足 \(0\leq l<r\leq 10^9\) 的使 \(f(l,r)\) 最大的数对 \((l,r)\)。如果有多种答案,请输出 \(l\) 最小的一种。如果仍有多种答案,请输出 \(r\) 最小的一种。

分析

好题好题。(ABC346G 的加强版)

参考:https://atcoder.jp/contests/abc360/submissions/55089328

这思路太棒了。

由题意,如果 \([l,r]\) 要和 \([L,R]\) 交叉的话需满足 \(0\leq l< L\)\(L<r<R\)\(L<l<R\)\(R<r\leq inf\)

那么在平面直角坐标系中,有两个矩形,其中一个的顶点为 \((0,L+1)\)\((L-1,R-1)\),另一个的顶点为 \((L+1,R+1)\)\((R-1,inf)\),在这两个矩形之一中的任意一点 \((l,r)\) 都满足要求。如图。

对于所有的 \(N\) 个区间 \([L_i,R_i]\),都可以产生这样的两个矩形,题目就转化成求一个点 \((l,r)\),覆盖它的矩形个数是最多的。

不是很记得扫描线怎么写了……

提交记录

G

题意

有一个长度为 \(N\) 的数组 \(A\)。随机选取一个 \(1\)\(N\) 之间的整数 \(x\),把 \(A_x\) 换为任意整数。求操作后 \(A\) 的最长上升子序列的最大长度。

分析

参考博客

提交记录

ABC365

E

题意

给你一个长度为 \(N\) 的整数序列 \(A=(A_1,\ldots,A_N)\)。求以下表达式的值:

\(\displaystyle \sum_{i=1}^{N-1}\sum_{j=i+1}^N (A_i \oplus A_{i+1}\oplus \ldots \oplus A_j)\)

分析

容易想到令 \(s_i\) 表示 \(A_1\)\(A_i\) 的前缀异或和。则答案被转换为 \(\sum\limits_{i=1}^{N-1}\sum\limits_{j=i+1}^{N}s_j\oplus s_{i-1}\)。直接计算时间复杂度为 \(O(n^2)\)

考虑每个 \(s_j\) 与前面的 \(s_{i-1}\) 对答案的贡献。两个数按位异或时,对于每一位,与自己当前位上相反会产生位权的贡献,与自己当前位上相同就不会产生贡献。那么可以开一个数组 \(cnt_{i,0/1}\) 表示有多少个数在第 \(i\) 位上为 0 或 1,每加入一个 \(s\) 就更新一次数组,同时计算答案,即把答案加上 \(\sum\limits 2^i\times cnt_{i,t_i\oplus 1}\),其中 \(t_i\) 表示 \(s\)\(i\) 位上的数。

时间复杂度 \(O(n\log A)\)

提交记录

ABC366

E

题意

给你一个二维平面上的 \(N\)\((x_1, y_1), (x_2, y_2), \dots, (x_N, y_N)\) 和一个非负整数 \(D\)

求使得 \(\displaystyle \sum_{i=1}^N (|x-x_i|+|y-y_i|) \leq D\) 的整数对 \((x, y)\) 的个数。

分析

观察到 \(\sum\limits_{i=1}^{N}(|x-x_i|+|y-y_i|)\) 这个数的计算不需要依赖 \((x_i,y_i)\) 的对应关系,即可以转化成 \(\sum\limits_{i=1}^{N}|x-x_i|+\sum\limits_{i=1}^{N}|y-y_i|\)。设枚举范围的大小为 \(T\)。(\(T\)\(N\) 同阶)

计算每个 \(x\) 对应的 \(\sum\limits_{i=1}^{N}|x-x_i|\) 可以从 \(O(N)\) 优化到 \(O(\log N)\)。先把所有点的横坐标排序,并求出前缀和 \(s\),对于每个 \(x\),二分找出它在横坐标中的位置,得到小于 \(x\) 的数的个数 \(t\)\(\sum\limits_{i=1}^{N}|x-x_i|=s_n-s_t-x(n-t)+xt-s_t\)。对于纵坐标同理。连同排序,预处理求出枚举范围中的每个 \(x\)\(y\) 对应的贡献的时间复杂度 \(O(N\log N+N+T\log N)=O(N\log N)\)

把上面求出的每个 \(x\) 的贡献排序,枚举 \(y\),二分求出有多少个 \(x\) 满足条件,相加即可。时间复杂度 \(O(N\log N)\)

总时间复杂度 \(O(N\log N)\)

注意:\(x\)\(y\) 的枚举范围都是 \(-2\times 10^6\)\(2\times 10^6\),存贡献的数组要开到 \(4\times 10^6\)。如果枚举范围只有 \(-10^6\)\(10^6\) 会被极限数据卡掉。

提交记录

F

题意

给你 \(N\) 个线性函数 \(f_1, f_2, \ldots, f_N\),其中 \(f_i(x) = A_i x + B_i\)

求由 \(K\) 个介于 \(1\)\(N\) 之间不同整数组成的序列 \(p = (p_1, p_2, \ldots, p_K)\) 的最大可能值 \(f_{p_1}(f_{p_2}(\ldots f_{p_K}(1) \ldots ))\)

分析

套路化地,先来考虑 \(f_i(f_j(x))>f_j(f_i(x))\) 需要满足什么条件。

\[A_i(A_jx+B_j)B_i>A_j(A_ix+B_i)B_j\\ \dfrac{A_i-1}{B_i}>\dfrac{A_j-1}{B_j} \]

故使得 \(f_{p_1}(f_{p_2}(\ldots f_{p_K}(1) \ldots ))\) 最大的序列 \(p\),一定满足 \(\frac{A_{p_1}-1}{B_{p_1}}\geq\frac{A_{p_2}-1}{B_{p_2}}\geq\dots\geq\frac{A_{p_K}-1}{B_{p_K}}\)

先将原来的函数按 \(\frac{A_i-1}{B_i}\) 从大到小排序,那么问题就转化成了求一个贡献最大的 \(K\) 长子序列。这个问题可以用动态规划解决。

\(dp_{i,j}\) 选到第 \(i\) 个函数,总共选了 \(j\) 个函数的最大贡献。对一个函数只有选与不选两种情况,得到状转方程:

\(dp_{i,j}=\max(dp_{i-1,j},dp_{i-1,j-1}\times A_i+B_i)\)。时间复杂度 \(O(NK)\)

注意函数在计算的时候是从内层往外算的,所以函数的排序实际上是按 \(\frac{A_i-1}{B_i}\) 小到大排序。

提交记录

ABC368

E

题意

在 Atcoder 国家,有 \(N\) 座城市,编号为 \(1\)\(N\),以及 \(M\) 列火车,编号为 \(1\)\(M\)\(i\) 次列车在 \(S_i\) 时从城市 \(A_i\) 出发,在 \(T_i\) 时到达城市 \(B_i\)

给定一个正整数 \(X_1\),求一个满足下列条件的非负整数 \(X_2,\ldots,X_M\) 的最小值 \(X_2+\ldots+X_M\)

  • 条件对于所有满足 \(1 \leq i,j \leq M\) 的一对 \((i,j)\),如果 \(B_i=A_j\)\(T_i \leq S_j\),那么 \(T_i+X_i \leq S_j+X_j\)
    • 换句话说,对于任何一对原本可以换乘的列车,即使将每趟列车 \(i\) 的出发和到达时间延迟 \(X_i\) ,仍然可以换乘。

可以证明,这种将 \(X_2,\ldots,X_M\) 设置为 \(X_2+\ldots+X_M\) 的最小值的方法是唯一的。

分析

贪心。每一辆从 \(s\) 站点出发的列车都要等到在它之前到 \(s\) 的列车全部到了再出发。

提交记录

G

题意

给定两个长度为 \(N\) 由正整数组成的序列 \(A\)\(B\),有以下 \(Q\) 个操作:

  • 给定两个正整数 \(i,x\),把 \(A_i\) 修改为 \(x\)

  • 给定两个正整数 \(i,x\),把 \(B_i\) 修改为 \(x\)

  • 给定两个正整数 \(l,r\),求出以下问题的答案:

    • \(v\) 设为 \(0\)。按 \(i=l,l+1,\dots,r\) 的顺序,把 \(v\) 替换为 \(\max(v+A_i,v\times B_i)\)。求最终的 \(v\) 值。 保证答案不超过 \(10^{18}\)

分析

因为 \(v\) 不超过 \(10^{18}<2^{60}\),所以对于每次查询,乘的次数一定不超过 \(60\) 次。并且如果乘的数为 \(1\),显然选择加比选择乘更优。所以把大于 \(1\)\(B_i\) 的下标都放进一个 set 里,对于每次查询,把 \([l,r]\) 区间内的那些大于 \(1\)\(B_i\) 都挑出来用乘法,其他的部分都用加法。还需要一个支持单点修改、区间查询的树状数组来维护 \(A_i\) 的区间和。时间复杂度 \(O(N\log^2 N)\)

我有一个疑惑,就是为什么用 *st.lower_bound(l) 会比用 *lower_bound(st.begin(),st.end(),l) 要快很多?

后者的提交记录

前者的提交记录

ABC369

F

题意

有一个网格,网格中有 \(H\) 行和 \(W\) 列。让 \((i,j)\) 表示从上往下数第 \(i\) 行,从左往右数第 \(j\) 列的单元格。

在这个网格中有 \(N\) 枚硬币,通过 \((R_i,C_i)\) 单元格可以拾取第 \(i\) 枚硬币。

你的目标是从 \((1,1)\) 单元格开始,反复向下或向右移动一个单元格,到达 \((H,W)\) 单元格,同时尽可能多地拾取硬币。

请找出您能拾取的最大硬币数以及能达到最大值的路径之一。

分析

赛时打算冲一下 A 六题的,结果脑子短路了,没想到怎么记录答案。不过已经是历史最好成绩了。赛后感觉这题只有绿。

显然,对于每一行,把本行要取的硬币全部取完了才能取下面的,且下面取的硬币的 \(y\) 坐标都要大于等于本行最右一枚硬币的 \(y\) 坐标。容易想到把所有硬币按 \(x\) 坐标排序,\(x\) 坐标相同的按 \(y\) 坐标排序,求 \(y\) 坐标的最长不下降子序列。

重点是输出方案。只要确定了被选出的硬币,那么输出就是一件很简单的事情。设有两枚硬币 \(u,v\) 是在路径上相邻的,那么这两枚硬币之间的路径就是 \(|x_v-x_u|\) 个向下的移动和 \(|y_v-y_u|\) 个向右的移动。

都知道动态规划能轻松解决最长不下降子序列的长度,那么怎么确定被选出的硬币是哪些呢?这在我看来是本题最大的难点。赛时就是因为没想出来这个然后寄了。

开几个名为 \(pre,g,t,d,f\) 的数组。

\(pre_i\) 表示路径中第 \(i\) 个硬币的编号。输出要用。

\(g_i\) 表示硬币 \(i\) 的上一个硬币编号。\(t_p\) 表示长度为 \(p\) 的最长不下降子序列的最后一个硬币编号。这两个数组对于求出路径至关重要。

剩下的都是常规操作:

\(d_p\) 表示长度为 \(p\) 的最长不下降子序列的最后一个硬币的 \(y\) 坐标。

\(f_i\) 表示以硬币 \(i\) 结尾的最长不下降子序列的长度。

vector<int>pre;
void putpre(int x){
	if(!x)return;
	putpre(g[x]);
	pre.push_back(x);
}
//---------------
int p;
for(int i=1;i<=n;i++){
	p=upper_bound(d,d+len+1,b[i])-d;
	if(p>len)len=p;
	f[i]=p;
	g[i]=t[p-1];
	d[p]=b[i];
	t[p]=i;
}
cout<<len<<endl;
pre.push_back(0);
for(int i=1;i<=n;i++){
	if(f[i]==len){
		putpre(i);
		break;
	}
}

完整代码:

const int N=200005;
int h,w,n;
struct node{
	int r,c;
}a[N];
int b[N];
bool cmp(node x,node y){
	if(x.r!=y.r)return x.r<y.r;
	return x.c<y.c;
}
int len,d[N],t[N],f[N],g[N];
void print(int x,int y){
	for(int i=1;i<=a[y].c-a[x].c;i++)cout<<"R";
	for(int i=1;i<=a[y].r-a[x].r;i++)cout<<"D";
}
vector<int>pre;
void putpre(int x){
	if(!x)return;
	putpre(g[x]);
	pre.push_back(x);
}
int main(){
	cin>>h>>w>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i].r>>a[i].c;
	}
	sort(a+1,a+1+n,cmp);
	for(int i=1;i<=n;i++)b[i]=a[i].c;
	int p;
	for(int i=1;i<=n;i++){
		p=upper_bound(d,d+len+1,b[i])-d;
		if(p>len)len=p;
		f[i]=p;
		g[i]=t[p-1];
		d[p]=b[i];
		t[p]=i;
	}
	cout<<len<<endl;
	pre.push_back(0);
	for(int i=1;i<=n;i++){
		if(f[i]==len){
			putpre(i);
			break;
		}
	}
	for(int i=1;i<=a[pre[1]].c-1;i++)cout<<"R";
	for(int i=1;i<=a[pre[1]].r-1;i++)cout<<"D";
	for(int i=1;i<len;i++){
		print(pre[i],pre[i+1]);
	}
	for(int i=1;i<=w-a[pre[len]].c;i++)cout<<"R";
	for(int i=1;i<=h-a[pre[len]].r;i++)cout<<"D";
	return 0;
}

ABC370

D

题意

\(H\times W\) 的网格,初始时每个网格都是黑色。给定 \(Q\) 个操作,第 \(i\) 个操作有两个数 \(R_i,C_i\),如果 \((R_i,C_i)\) 是黑色的,就把它涂成白色。否则将其上下左右的第一个黑色格子涂成白色。

分析

本来想从 D 开题,看到这个题目就赶紧跑了。切完 ABC 回来发现题面纯纯诈骗。算了反正 ABC 题目就这个风格。

看到题第一反应是并查集,但我不太会写。然后就写了链表,写了两遍发现都假掉了,因为链表无法维护删除之后的点的邻接元素。最终用 set+二分过了。说实话并不难想。

提交记录

E

题意

给定一个长度为 \(N\) 的序列 \(A=(A_1,A_2,A_3,\dots,A_N)\) 和一个整数 \(K\)。求把它分成若干个连续子序列的方案中,每一个子序列内部元素的和都不等于 \(K\) 的方案数。对 \(998244353\) 取模。

分析

赛时想出 DP 方程,但看到所剩时间不多了,就摆了,也没怎么去想优化。赛后发现比上次那道 E 还简单。

\(dp_n\) 为选到第 \(n\) 个数的方案数。\(dp_n=\sum\limits_{0\leq m< n}dp_m[\sum\limits_{i=m+1}^{n}A_i\not=K]\)

前缀和优化一下:\(dp_n=\sum\limits_{0\leq m< n}dp_m[S_n-S_m\not=K]\)

再优化一下:\(dp_n=\sum\limits_{0\leq m< n}dp_m-\sum\limits_{0\leq m< n}dp_m[S_m=S_n-K]\)

\(B_k\) 为满足 \(S_i=k\)\(dp_i\) 总和。可用 map 维护。

\(dp_n=\sum\limits_{0\leq m< n}dp_m-B_{S_n-K}\)

提交记录

ABC371

E

题意

给定一个长度为 \(N\) 的数列 \(A=(A_1,A_2,\dots,A_N)\)。定义 \(f(i,j)\)\((A_i,A_{i+1},\dots,A_j)\) 中不同元素的种类数。求 \(\sum\limits_{i=1}^{N}\sum\limits_{j=i}^{N}f(i,j)\)

分析

I Hate Sigma Problems.

最近的 E 好像一次比一次简单了。

考虑枚举右端点。记 \(lst_{i}\)\(i\) 这个数最后一次出现的位置。每次在右端加入一个数,对前面所有左端点的影响:对 \(1\)\(lst_i\) 的位置没有影响,对 \(lst_{i}+1\) 到当前位置有影响。然后我就写了线段树,其实没必要。 统计答案并更新 \(lst_i\)

提交记录

F

题意

在数轴上有 \(N\) 个人,每个人的坐标为 \(X_i\)

你可以执行以下操作任意次:

  • 选择一个人。如果目的地没有其他人,将这个人向左或向右移动 \(1\) 米。

\(Q\) 个任务,每个任务内容如下:

  • 将第 \(T_i\) 个人移动到位置 \(G_i\)

你需要按顺序完成所有任务,求最少进行多少次操作。

分析

联合省选 2025 D2T1 原题。

观察样例可知,移动一个人时,可能把移动方向上的连续的几个人一起移动。移动后的人的位置形成了公差为 \(1\) 的等差数列。

一个 trick:把第 \(i\) 个人的位置减去 \(i\),等差数列中的数就变成了一段相同的数。这样位置的改变就转化成了区间赋值,可以用线段树维护。

对于每次移动,在线段树上二分出离这个人最近的不需要移动的人。设他的编号为 \(j\),当前位置为 \(p_j\)额外移动的人的个数为 \(num\)。以向左移动为例,有:

\[G_i-num>p_j \]

又因为 \(num=T_i-j-1\)

\[G_i-T_i+j+1>p_j \]

移项得

\[G_i-T_i>p_j-j-1 \]

\[G_i-T_i \geq p_j-j \]

向右移动同样可得 $$G_i-T_i \leq p_j-j$$。

求出 \(j\) 后,可以算出移动的次数。

提交记录

ABC373

E

题意

正在举行一次选举,有 \(N\) 名候选人,编号为 \(1,2,\ldots,N\)。一共有 \(K\) 票,现在已经统计了部分的票。

到目前为止,计票结果是 \(A_i\) 票投给了编号为 \(i\) 的候选人。

计票结束后, \(i\) 号候选人 \((1 \leq i \leq N)\) 将当选,当且仅当得票多于该候选人的候选人少于 \(M\)。可有一名以上候选人当选。

求每个候选人在剩余的 \(K-\sum_{i=1}^{N}A_i\) 选票中至少需要获得多少票才能一定当选。

分析

观察到答案具有单调性,二分该候选人接下来得到的票数,然后判断。

判断运用贪心,即尽量让该候选人无法当选。

如果这个候选人加上 \(mid\) 票后,比他得票多的人还大于等于 \(M\),那么肯定不行。

否则考虑把剩下的 \(K-mid-\sum_{i-1}^{N}A_i\) 分给在前 \(M\)(排除掉该候选人)但得票小于等于 \(A_i+mid\) 的人,让他们的票数都大于 \(A_i+mid\),让该候选人落选。把所需票数和实际剩余票数进行比较。

提交记录

F

题意

\(N\) 类物品。其中 \(i\) 类物品的体积为 \(w_i\),价值为 \(v_i\)。每种类型都有 \(10^{10}\) 个可用物品。

高桥打算选择一些物品,把它们装进一个容量为 \(W\) 的袋子里。他将选择 \(k_i\)\(i\) 类型的物品的快乐值定义为 \(k_i v_i - k_i^2\)。请计算他能获得的最大快乐值。

分析

因为体积为 \(w_i\) 的物品最多放 \(\left\lfloor\frac{W}{w_i}\right\rfloor\) 件,借鉴 ABC365E,考虑使用调和级数相关的做法。

把物品按体积分类,令 \(C_{i,j}\) 为体积为 \(i\) 的物品中选 \(j\) 件的最大快乐值,这个可以优先队列+贪心预处理。然后枚举体积和每种体积选的物品个数。时间复杂度 \(O(W^2\ln W)\)​。

提交记录

ABC375

E

题意

\(N\) 人分成三个小组。

人数编号为 \(1, 2, \ldots, N\),团队编号为 \(1, 2, 3\)。目前,\(i\) 属于 \(A_i\) 小组。

每个人都有一个名为强度的值,\(i\) 的强度为 \(B_i\)。一个团队的强度被定义为其成员强度的总和。

确定是否可能有零个或更多的人交换团队,从而使所有团队的实力相等。如果可能,求最少需要多少人换队才能达到这个目的。

除了 \(1\)\(2\)\(3\) 队之外,您不能创建新的队。

  • \(3 \leq N \leq 100\)
  • \(A_i \in \lbrace 1, 2, 3 \rbrace\)
  • 每个 \(x \in \lbrace 1, 2, 3 \rbrace\) 都存在一些 \(i\) 满足 \(A_i = x\)
  • \(1 \leq B_i\)
  • \(\displaystyle\sum_{i = 1}^{N} B_i \leq 1500\)
  • 所有输入值均为整数。

分析

赛后过来看一眼这不是 DP 大水题吗。这么说这场我其实每题都会做。为什么我赛时没切,后悔莫及。

看到数据范围,可以确定 \(B_i\) 能够写进 DP 状态。然后很容易想到状态 \(dp_{i,j,k}\),最终答案为 \(dp_{N,\frac{S}{3},\frac{S}{3}}\)。状态是啥就懒得写了,反正赛后一看就出来了。

提交记录

G

题意

在 AtCoder 国家中,有 \(N\) 座城市,编号为 \(1\)\(N\),以及 \(M\) 条道路,编号为 \(1\)\(M\)
道路 \(i\) 双向连接城市 \(A_i\)\(B_i\),长度为 \(C_i\)

对于每个 \(i = 1, \ldots, M\),判断下列两个值是否不同。

  • 当所有道路都可以通行时,从城市 \(1\) 到城市 \(N\) 的最短距离
  • 当除道路 \(i\) 之外的道路 \(M - 1\) 均可通行时,从城市 \(1\) 到城市 \(N\) 的最短距离

如果在其中一种情况下可以从城市 \(1\) 到达城市 \(N\),而在另一种情况下则不能,则这两个值被认为是不同的。

分析

首先建出最短路图。对于每一条边,检查它是否是最短路图的割边即可。

最短路图的建法:

对于无向图,从 \(1\)\(N\) 号点分别跑一次最短路,对于每条边 \((u,v)\),若 \(dis_u+w+dis2_v=dis_n\)\(dis_v+w+dis2_u=dis_n\),则这条边在最短路图上。

提交记录

posted @ 2025-06-01 17:04  Snowhats  阅读(13)  评论(0)    收藏  举报