2025暑假集训做题记录

luogu P7118 Galgame

前置

  • \(n\) 个点的二叉树形态总数是 \(Catalan(n)\)。递推公式:$$\frac{Cat(n)=Cat(n-1)\times(4n-2)}{n+1}$$。

solution

没有给定 gal 有趣的 gal 可以分成两类:节点个数比它少 和 其它。

节点个数比它少的可以直接用 \(Cat(siz_u)\) 计算。接下来考虑剩下的情况。

对于递归进去处理的一个节点 \(u\)

  • 若当前左子树的 \(siz\) 比给定小,一定满足条件。即 \(\sum _{i=0}^{siz_{lson_u}-1} Cat(i)\times Cat(siz_u-1-i)\)

  • 左子树的 \(siz\) 与给定一样,但有趣度更少。此时右子树的形态是随意的。所以递进去处理,同时带上 \(Cat(siz_{rson})\) 的系数。

  • 右子树的 \(siz\) 与给定一样,但有趣度更少。因为左子树的形态必须与给定一致所以没有系数。

这样的复杂度是 \(O(n^2)\) 的。瓶颈在于第一种情况,当 \(siz_{lson}\) 大的时候非常不优。

但我们发现 \(Cat(siz_u)=\sum _{i=0}^{siz_{lson_u}} Cat(i)\times Cat(siz_u-1-i)+\sum _{i=siz_{lson_u}}^{siz_u-1} Cat(i)\times Cat(siz_u-1-i)\),而前后的枚举个数和是 \(siz_u\),所以当第一项大时可以用总的减去第二项。此时复杂度显然是 \(\log\) 的。

于是做到 \(O(n\log n)\)

某模拟赛神秘题

http://goj.wiki/d/Union2024/p/853?tid=686bd4da0e50d6389dc89526

给你一个 \(n\) 个点的“堆”,但每个节点不一定只有两个子节点。对每个点进行编号,编号满足堆的条件。给你一个排列 \(q_i\),求给每个位置赋值使得值的大小满足堆的条件,且字典序小于等于 \(q\) 的情况下字典序最大的排列 \(p\),并求满足字典序小于等于 \(q\) 且满足堆条件的排列方案数。

1

考虑贪心。按照编号顺序一个个填。

已经填完的数一定形如包含根的一个连通块。扣去当前要填的数,剩下要填的数类似组成几个子树。

几个子树各有上面传下来的一些限制。考虑当前限制最大是多少。

显然,给一棵树一些数,一定有合法的填法。所以在考虑子树时只考虑给每个子树分哪些数填。\(^1\)

对于每个子树的限制排序,从小到大填。如果当前填到了一个 \(a\),但是下一个子树的限制是 \(a+?\),那么显然 \(a\) 只能填到当前的位置上。填的时候如果不满足字典序就和 \(q_u\)\(\min\)

为什么子树 \(q\) 的限制一定能满足?若不满足,则说明填的数 \(>q_u\),那把 \(q_u\) 直接换进当前位置即可。只是改了分配的数所以还是有合法的填法。

2

\(f_u\) 为以 \(u\) 为根,有 \(siz_u\) 个数,有多少种填数方法。

枚举第一位小于 \(q\) 的位置 \(i\)。前面的数完全按照最大的去填。剩下子树的 limit 是很多个 \(\ge ?\) 和特殊的 \(i\)\(\ge?\)\(<q_i\))。发现 \(i\) 的限制可以转换为全都是 \(\ge ?\) 的方案数减去 \(\ge q_i\) 的方案数。按照限制从大到小计算,式子是容易的,不进行展开。

没了啊?。

咕咕咕。

CF538G

P7320

考虑叶子,如果有点集直接输出。边集在叶子间连边即可。

AT_arc103_d

\(D_u\) 最小的一定是叶子,通过等式找到这个叶子一定会和什么点连边,递下去找。

CF611H

转化为多个点集?大概是枚举一条边删掉之后是否合法然后暴力做。

CF131E

归纳到 \(n-6\),小情况暴力。

upd:但是到要暴力到12内。(貌似)更优越的做法:直接选那些点染成什么色。

CF1270E

发现不交非常难刻画,所以取模。发现欧几里得距离是平方,而平方对 4 取模有良好的性质。对原网格黑白染色,如果有颜色不同的点就直接输出(同色的点之间距离模 4 一定是 0/2,反之是 1),否则将网格旋转 45度 继续做。

AT_agc027_d

把网格黑白染色然后转化成黑mod白。如果白固定了,黑直接取 \(lcm(a,b,c,d)+1\) 即可。发现这样无法保证黑格的数互不相同,考虑白格全部取质数。但这样太大了无法接受。神秘构造方法:对于每一条对角线的白格(正着反着都算)乘一个素数。容易发现这样符合条件。

CF804E

只有在 \(n \mod 4 =0 or 1\)时有解。归纳至 \(n-4\)

大概酱:

CF1690G Count the Trains

唉唉还是没有蓝色思维。

\(O(n)\) 维护出一开始的答案是容易的。

考虑对于一个修改 \(x,y\),对答案有什么影响:

  • \(x\) 后面的任意车头 \(v \ge a_x-y\) 那么会被合并到当前这节火车(并不需要知道车头是多少)。
  • \(x\) 前面的一节车头如果 \(v>a_x-y\) 那么这节火车就会在 \(x\) 处断开,\(x\) 成为新的一节火车车头。

用 set 维护两个操作。于是做到 \(O(n \log n)\)

Submission。

CF1638E Colorful Operations

考虑维护每个颜色的总 tag,线段树维护每个区间的区间加标记,颜色覆盖标记。每次修改颜色的时候递归到区间颜色只有一种再操作,区间覆盖颜色,区间加上原来颜色的 tag,减去修改后颜色的tag(这个tag之前操作的时候并不影响到当前区间,但是后面计算当前区间的时候会算上,所以减掉贡献。)。查询由于是单点直接做就好了。

考虑这么暴力为什么复杂度是对的。感性理解就是,一个颜色区间只会在被覆盖时贡献 \(O(1)\) 的复杂度。又知道一个颜色区间并不能被贡献很多次(如果可以的话那每次修改的区间也仅仅是 \(O(1)\) 的,不然就会完全覆盖掉一个区间。)。

Submission

这个均摊非常的妙啊。原理应该跟珂朵莉树类似,但是不想学,咕咕咕。

AT_agc061_c [AGC061C] First Come First Serve

随便选是 \(2^n\) 的。考虑何时会算重。

\([a_i,b_i]\) 中没有人时,第 \(i\) 个人的选择就是不影响顺序的,就算重了。

所以转化成算每个人的选择满足下列条件的方案数:

  • \(a_i\)
  • \([a_i,b_i]\) 中有至少一个人,选 \(b_i\)

考虑容斥变成:

  • \(a_i\)\(b_i\)
  • 减去 \([a_i,b_i]\) 没有人的选 \(b_i\) 的情况。

\(dp_i\) 表示前 \(i\) 个人考虑容斥系数的方案总数。第一种转移是显然的。考虑第二种转移,对每个 \(i\) 找出跟它无交的最后一个位置 \(l_i\),跟它有交的最后一个位置 \(r_i\)。若 \([a_i,b_i]\) 为空,那么 \([l_i,r_i]\) 的选法就是固定的(因为这中间的位置有一个端点在 \([a_i,b_i]\) 内。)于是 \(dp_{r_i} \gets -dp_{l_i}\)

\(l_i,r_i\) 求出是简单的。复杂度 \(O(n)\)

U486901 传送

线段树分治好题,傻逼评测机波动。

description

给你一个无向图,第 \(i\) 条边 \((a,b)\) 会在 \([l,r]\) 时刻出现。假设所有能从 \(1\) 到达 \(i\)\(k\) 时间点为 \(t_{i, 1},\cdots,t_{i,k}\),,求 \(\operatorname{xor}_{i = 1} ^ n (\sum_{j = 1} ^ k t_{i,j})\)

solution

一看就是线段树分治。考虑暴力做法,每次分治到 \((i,i)\) 时把和 \(1\) 一个连通块的点答案全部 \(+i\)。这样显然是 \(O(n^2\log n)\) 的,无法通过。

但是我们并不需要时刻知道每个点的答案,所以考虑对于每个点维护一个 \(tag\),代表每个点给它的子树的贡献。后面的想法比较自然,把 \(i\) 并入 \(j\) 时,\(tag_i\gets tag_i-tag_j\),因为 \(j\) 之前的 \(tag\) 并不需要加到 \(i\) 上,但最后会计算到。把 \(i\) 分离 \(j\) 时,\(tag_i\gets tag_i+tag_j\) 即可。最后每个点的答案就是 \(tag_u\)

时间复杂度 \(O(n\log^2 n)\)(吗)。

corner case 1

为什么在把 \(i\) 分离 \(j\) 时不用算更高的祖先的贡献?

考虑可撤销并查集的性质,分离的时候一定和合并的时候形态一样。那么 \(j\) 一定是根。

submission

卡了很多发。link

2025.7.25模拟赛 D交集

改出这题需要感谢:lzy(优秀的讲题),ymy(调出关键一步),lhl(提供多个可用hack),chx,yjc 以及 ljq(提供对拍代码)。

题意

数轴上有 \(n\) 条线段。定义一组线段的价值为该组所有线段的交集长度。并且要求每一组的价值都至少为 \(1\),现要求把这些线段恰好分为 \(k\) 组是的这 \(k\) 组的价值总和最大,输出这个值。无解输出 \(0\)

solution

线段之间没有完全包含关系的时候是简单的。设 \(dp_{i,j}\) 表示到第 \(i\) 条线段,分了 \(j\) 组的最大价值和。直接单调队列 dp 即可,由于自己写出来了就不展开了(虽然还是错完了)。这里复杂度 \(O(nk)\)

如果有包含关系,设所有 完整包含了其它至少一条线段 的线段为“大线段”。那么如果“大线段”要和其它任何线段分到同一组,和它包含的线段(如有多条任意一条)放一组是不劣的,因为这样并不会影响答案贡献。否则就自己一组。

枚举有几条“大线段”自己一组,直接取它们之中最长的就行。

写出来大概就是:

\[\max_{i=1}^k dp_{n,i}+sum_{k-i} \]

其中 \(sum_i\) 表示前 \(i\) 大的“大线段”和。

复杂度 \(O(nk)\)

code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define pii pair<int,int>
#define fi first
#define se second
#define mkp make_pair
const int maxn=5004,inf=1e9+1121;
int n,m;
pii o[maxn];
struct node{int l,r;}a[maxn];int na; 
int len[maxn],nb;
int dp[maxn][maxn];
deque <int> p[maxn];
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>o[i].fi>>o[i].se;
	sort(o+1,o+1+n);
	for(int i=1;i<=n;i++){
		bool fl=0;
		if(o[i]==o[i+1]){len[++nb]={o[i].se-o[i].fi+1};continue;}//对于完全相同的线段只保留一条
		for(int j=i+1;j<=n;j++){
			if(o[i].se>=o[j].se){fl=1;len[++nb]={o[i].se-o[i].fi+1};break;}
		}if(fl) continue;
		for(int j=i-1;j>=1&&o[j].fi==o[i].fi;j--) if(o[j].se<o[i].se){fl=1;len[++nb]={o[i].se-o[i].fi+1};break;}//判“大线段”
		if(!fl) a[++na]={o[i].fi,o[i].se};
	}sort(len+1,len+1+nb,greater<int>());//取最大的“大线段”
	dp[0][0]=0;p[0].push_back(0);
	for(int i=1,j;i<=na;i++){
		dp[i][0]=-inf;
		for(int k=min(i,m);k>=1;k--){
			while(p[k-1].size()&&a[p[k-1].front()+1].r<a[i].l) p[k-1].pop_front();
			if(p[k-1].size()){
				j=p[k-1].front();
				dp[i][k]=dp[j][k-1]+a[j+1].r-a[i].l+1;
				while(p[k].size()&&dp[p[k].back()][k]+a[p[k].back()+1].r<=dp[i][k]+a[i+1].r) p[k].pop_back();
				p[k].push_back(i);
			}
			else dp[i][k]=-inf;
		}
	}//dp
	int ans=0;int sum=0;
	for(int i=0,lim=min(nb,m);i<=lim;i++){sum+=len[i]; ans=max(ans,dp[na][m-i]+sum);} 
	cout<<ans<<'\n';
	return 0;
}

Submission。

7.26模拟赛T2 P1537 硬币机

题意

你有 \(n\) 个物品,可以按顺序得到 \(a_i,b_i,a_i\) 的价值。问对于每个 \(i(1\le i \le m)\) ,取 \(i\) 次可以取到的最大价值。

\(n\le 10^5,m\le 10^6\)

场上想到

转化成一个体积为 \(1\) 价值为 \(a_i\) 的物品和一个体积为 \(2\) 和价值为 \(a_i+b_i\) 的物品,容易发现这样可以覆盖所有情况。

把所有物品按照“性价比”排序。

然后开始乱贪,显然假完了。

solution

做法来自 ymy,听起来是对的。

把体积为 \(2\) 的物品和体积为 \(1\) 的物品分开。设总共取了体积为 \(i\) 的物品,有 \(j\) 个是体积为 \(2\) 的物品。发现随着 \(i\) 的增大 \(j\) 不会减小,拿指针维护 \(j\) 即可。

upd on 7.29

呃呃呃昨天突然感觉我的做法没有甲烷。逻辑链十分严密啊。

最后 ymy 大师给拍出来了。没有特判 \(W>3n\) 的情况,判完就对完了。

我吃柠檬。

补一下贪心细节:如果直接按顺序拿能正好放完所有体积肯定是对的,剩下的情况只有“下一个物品体积为 \(2\),但剩余体积为 \(1\)”这种。那么显然我们有两种选择:

  • 放掉当前物品,找下一个体积为 \(1\) 的物品。
  • 放掉上一个体积为 \(1\) 的物品,取当前物品。

于是预处理出对于每个 \(W\) 按顺序取可以取到哪里,上一个 \(1\) 的位置,下一个 \(1\) 的位置。按思路模拟即可。

Submission

7.28

P1397 [NOI2013] 矩阵游戏

solution

容易发现题目中的转移矩阵形式都是:

\[A= \begin{bmatrix} a & 0 \\ b & 1 \end{bmatrix} \]

(因为太不会 latex 了,所以下面摘一段题解。)

\(a\ne 1\) 时,有

\[\begin{bmatrix}a & b\\ 0 & 1\end{bmatrix}^{P-1} = \begin{bmatrix}a^{P-1} & (a^{P-2}+\cdots+a+1)b\\0 & 1\end{bmatrix} \]

由费马小定理

\[a^{P-1}\equiv 1\pmod P \]

\[(a^{P-2}+\cdots+a+1)\equiv\dfrac{1-a^{P-1}}{1-a}\equiv 0 \pmod P \]

所以 \(\begin{bmatrix}a & b\\ 0 & 1\end{bmatrix}^{P-1}\) 在做 \(\bmod P\) 运算时就相当于单位矩阵 \(I\)

\(a=1\) 的情况特判即可。

Submission

P4301 [CQOI2013] 新Nim游戏

solution

显然先手一定有必胜策略。

考虑第一回合后手的操作,如果能够将剩下数的异或和操作成 \(0\) 那后手就必胜了。所以先手剩下的数里面一定不能有异或和为 \(0\) 的子集。

发现线性基里的数就具有这样美好的性质。但如何保证取的总数最小?

我们要求剩下的数的和最大,即线性基里的和最大。直接把 \(a_i\) 排序,从大到小插入。容易发现这样构造的线性基一定是和最大的。于是做完。

Submission

CF895C Square Subsets

solution

先把每个数里面的平方数除掉,这样不影响答案。这样每个质因数在一个数里出现的个数是 \(0\)\(1\)

最终是平方数等价于出现次数和是偶数,等价于出现次数异或和为 \(0\)。这样就非常像线性基了。

考虑对于线性基外的数的任意一个子集,它们异或起来的和一定和线性基内的一个唯一子集对应。所以线性基外的数随便取都是一种答案。设线性基的大小为 \(k\),则答案为 \(2^{n-k}-1\)(不能不选)。

Submission

7.29 咋提选讲

GDCPC2024F

题意

给你一个无向图,设 \(k=\lceil \frac{m}{n-1} \rceil\),问是否存在点对 \((u,v)\) 使得它们之间存在 \(k\) 条边不相交的路径。

\(n\le10^5,m\le2\times10^5\)

solution

\(k\) 相当于至多 \(n-1\) 条边一组至少分出的组数。看到 \(n-1\) 想到树,于是直接维护 \(k-1\) 棵生成树,每次从前往后插入一条边。若插入不了这条边说明已经有解了。这样枚举在 \(m>>n\) 时显然不行。

但是这玩意有单调性啊!于是做完。

upd

细节巨多啊,复杂度大概是 \(O(log^2)\) 的。

Submission

AGC016E

solution

先考虑如何判断一只火鸡能不能留到最后。考虑倒退,如果一个人吃的火鸡是 \((x,i)\) 就说明 \(x\) 在此之前必须保留。对于每个 \(i\),处理出 \(S_i\) 表示有保留要求的 \(x\) 的集合。

经过一些分讨(写起来太麻烦了喵),发现 \(S_i \cup S_j\) 是可以保留 \(i,j\) 的充要条件。直接枚举即可。

Submission

P9731 [CEOI 2023] Balance

先考虑对于 \(S=2\) 怎么做。相差 \(\le1\) 的限制不好处理,考虑对于每个出现次数为奇数的题目添加一组为 \((x,0)\) 的评测,问题转化为两次评测数量相等。

若把先评测的向后评测连边,就变成找一个欧拉回路。因为度数都是偶数所以一定有解。

后面分治处理,咕咕咕。

upd

对于每一层,先通过找欧拉回路将其分成每个颜色出现次数之差不超过 \(1\) 的前后两个部分,分治进去处理就可以了。

图的构造方法是把颜色和层数分别对应连边。

补一手欧拉回路解法:在有解的情况下,dfs是有正确性的。每次直接遍历复杂度肯定假了(嘿嘿我不知道调了特别久然后又是 ymy 调出来的),但是你发现一条边不会用两次,所以当前弧优化,做完!

复杂度 \(O(ns\log s)\) 吧!

Submission

7.30【DIV1 & DIV2】模拟赛

T1 exam

description

给你 \(n\) 种题目,每种题目有 \(m\) 道。每种题目有固定的两个参数 \(a_i\)\(b_i\)。任意两道题目(包括合并过的)可以合并,合并后 \(a'=a_i+a_j,b'=b_i+b_j\)。每道题目的“爽度”定义为 \(\frac{b_i}{a_i}\)

给定两个整数序列 \(p_0=1,p_1,\cdots,p_k=100\)\(v1,\cdots,v_k\)。如果一道题目的爽度 \(\frac{b_i}{a_i} \in (\frac{p_{i-1}}{100},\frac{p_i}{100}]\),那么它的“开心度”为 \(a v_i\)

\(\sum a \le m\) 的最大开心度。保证 \(p\)\(v\) 单调递增。

\(n,m\le 8\times10^3\)

solution

我要锐评,本题难度主要在于读题和看到 \(v\) 单增。

因为对于每种题目都有 \(\sum a=m\),所以可以理解成取的数量没有限制。

做一次完全背包,对每个 \(i\) 预处理出 \(f_i\) 表示 \(\sum a=i\) 时最大的 \(\sum b\)

新的“物品”就变成体积为 \(i\),价值为 \(f_i\),再做一次完全背包即可。复杂度 \(O(nm)\)

记录详情 - Genisis Online Judge

T2 team

description

给你 \(n\) 个人,每个人有三个能力值 \(a_i,b_i,c_i\)。你需要选出三个人满足他们分别是三人中 \(a,b,c\) 最大的人。求 \(a,b,c\) 最大值的和的最大值。

\(n\le 1.5\times10^5\)

solution

如果没有三个人分别最大的限制直接分别取最大的求和即可。先把人分别按 \(a,b,c\) 降序排序,设当前选的人分别是 \(i,j,k\)(初始均为 \(1\)),不合法的情况当且仅当 \(a_i\le a_j\)\(a_i\le a_k\) ,对于 \(b_j\)\(c_k\) 同理。那考虑如果将 \(i\) 往后移,因为 \(a_i\) 排序后是单调不增的,所以还是解决不了矛盾。所以只能把 \(j\)\(k\))往后移。模拟即可。

赛场脑抽了用 set,直接用数组就行了。记录详情 - Genisis Online Judge

T3 memory

description

你需要维护 \(n\) 个可重集合 \(S_1, S_2, \ldots, S_n\),初始均为空集合。共有 \(m\) 次操作,操作分为三种类型:

  • 操作1:给定区间 \([l, r]\) 和数值 \(k\),对所有 \(i \in [l, r]\),在集合 \(S_i\) 中插入元素 \(k\)
  • 操作2:给定区间 \([l, r]\),首先计算这些集合的并集中的最大元素,若并集为空则跳过此操作。否则,对于所有 \(i \in [l, r]\),若 \(T \in S_i\),则从 \(S_i\) 中删除恰好一个 \(T\)
  • 操作3:给定区间 \([l, r]\),计算并输出这些集合的并集中的最大元素:若并集为空,则输出 \(-1\)

\(n,m\le 2\times 10^5\)

solution

几乎是暴力维护题。

感觉这个形式很像前几天做的那个颜色段均摊。所以建一棵线段树,每个节点用 multiset 维护区间插入的元素,和最大值(不要求是区间插入)。

  • 操作1:直接暴力插
  • 操作3:暴力查
  • 操作2:先用操作3查出最大值 \(ans\)。对于一个区间,如果它被完全覆盖并且区间插入的数中有 \(ans\),删掉即可。否则,若区间插入的数里有 \(ans\),把 \(ans\) 插入到左右儿子区间中。递归查询即可。

复杂度我也不知道多少,反正是对的!

记录详情 - Genisis Online Judge

posted @ 2025-07-24 11:33  Belliz  阅读(14)  评论(0)    收藏  举报