2026 - 7月测试思路总结
Day 1
T1
很明显,中位数位置前的数不必在意,模拟一下从前往后推即可
T2
二分套二分,先二分答案,在 \(check\) 里用二分优化复杂度
Day 2
T1
long long
二分答案,\(check\) 里遍历一遍即可
T2
\(ST\) 表模版,注意处理大小写即可
Day 3
T1
贪心
首先,三个一组,组组之间夹放 \(数量最多的花\)
然后,\(数量次大的花\) 和 \(数量最多的花\) 两个一组
一定有一种最优排列使得可以放下 \(数量次大的花+数量最少的花+1\) 数量个 \(数量最多的花\)
T2
观察题目可发现,两传送门之间的区域和外部是不联通的
内部运动近似环状,外部运动中数字的先后顺序不变,可将数字移动到内部数字前或后
所以所有排列一定是外部数字的某两个数字之间(或开头结尾)插入了整个内部数字
编码逻辑:
先分离内外部数字
再预处理出内部数字的最小字典序
遍历找到内部最小数字
以这个最小数字为开头遍历复制整个内部数字
- 遍历外部数字:
for
if(内部数字未输出 && 遍历到的数字 > 内部的第一个数字(即内部最小数字))
输出整个内部数字(内部数字的最小字典序)
输出遍历到的数字
- 循环结束后如果还没有输出内部数字的最小字典序则输出
多测要清空!
Day 4
T1
注意到神秘数据范围,所以直接 \(DFS\) 爆搜可过
T2
分治,考虑两种策略
- 全部竖着刷
- 先横着刷底座,再分治上半部分
最后用 \(ST\) 表优化至 \(O(nlog_2n)\) 即可过
Day 5
T1
把 \(0\) 看成 \(-1\) 找最长的区间和为0的区间
T2
\(BFS\)
初始将 参加了会议的人 进队,对应的 \(vis\) 设为 \(1\)
\(BFS\) :
- 取出队首 \((u)\)
- 遍历队首的所有边 \((v)\)
1. 检查 \(vis_v\) 是否有值,有值则 \(continue\)
2. 更新 \(vis_v=vis_u+1\)
3. 检查 \((1+day\_cnt) \times day\_cnt \div 2\) 是否 \(\leq vis_v\)是:\(ans_v=day\_cnt\)
否:\(ans_v=day\_cnt++\)4. 将 \(v\) 进队
因为 \(BFS\) 所以为正确最小值
Day 7
T1
多测,字符串,暴力
暴力查找是否有完整的一行红
没有则答案为蓝
T2
long long,位运算
答案为 \(n\) 转为 \(2\) 进制后的 长度\(+1\)的数量\(-2\)
T3
搜索
预处理一张地图,每个格子的权值为它被流星砸中的最早时间
然后 \(BFS\) ,只能走格子权值>走后时间的格子
T4
long long,贪心,ST,记忆化?
转化题意:
每轮给出 \(l_1,r_1,l_2,r_2\)
小L在 \(A_{l_1}\) 到 \(A_{r_1}\) 中选一个数
小Q在 \(B_{l_2}\) 到 \(B_{r_2}\) 中选一个数
得分为选的两数乘积
小L要让得分尽可能大,小Q要让得分尽可能小
Day 8
T1
long long,离散化,差分
T2
前缀和,dp?
已经不是语言能够很好表达的了,看代码了解一下我的思路吧
int n;
cin>>n;
for(int i=0;i<n;i++){
int a,b;
cin>>a>>b;
maxa=max(a,maxa);
input.push_back({a,b});
}
sort(input.begin(),input.end(),cmp);
int top=n-1;
for(int i=maxa;i>=0;i--){
sum[i]+=sum[i+1];
if(input[top].a==i){
++sum[i];
--top;
}
}
int ans=INT_MAX;
for(int i=1;i<n;i++){
int k=sum[max(0,input[i].a-input[i].b)]-sum[input[i].a];
dp[i]=dp[max(0,i-k-1)]+k;
ans=min(ans,dp[i]+n-i-1);
}
cout<<ans;
Day 9
T1
离散化,Map,循环结构
考虑桶排然后发现 \(10^9\) 原地爆炸,所以离散化
但是......
我选择Map
一20:00 才发现这个雷霆输入,骇死我了 QWQ一
T2
long long,字符串,DP
一说到总⻓度不超过 100000 我就想到 Trie 了一
分析题目:
-
很明显,本题只能最多支持 \(O(nlog_2n)\) 级别的算法
-
带权,贪心明显不可行
-
求单调不严格上升
e...... DP ?
状态定义:
-
\(dp_{i,0}\) 表示第 \(i\) 个字符串在不翻转情况下要让前 \(i\) 个字符串按字典序排列所需花费的最少能量
-
\(dp_{i,1}\) 表示第 \(i\) 个字符串在翻转情况下要让前 \(i\) 个字符串按字典序排列所需花费的最少能量
-
值为 \(INF\) 表示不可能
初始化:
dp[0]={0,input[0].val};
dp[X]={INF,INF};
状态转移:
if(input[i].in>=input[i-1].in)
dp[i].first=min(dp[i].first,dp[i-1].first);
if(input[i].in>=input[i-1].tmp)
dp[i].first=min(dp[i].first,dp[i-1].second);
if(input[i].tmp>=input[i-1].in)
dp[i].second=min(dp[i].second,dp[i-1].first+input[i].val);
if(input[i].tmp>=input[i-1].tmp)
dp[i].second=min(dp[i].second,dp[i-1].second+input[i].val);
//in为输入原始字符串,tmp为预处理的反转后字符串
//dp[X].first即dp[X][0]
//dp[X].second即dp[X][1]
答案:
int ans=min(dp[n-1].second,dp[n-1].first);
//如果ans等于INF则输出-1
Day 10
T1
贪心,模拟,本质是 \(k\) 进制
T2
背包 \(DP\) ,把时间当做重量,刷表法,用 \(ans\) 记录最小值即可
#include<bits/stdc++.h>
#define int long long
using namespace std;
struct Node{
int val,cnt;
};
Node dp[5005];
vector <pair <int,int> > input;
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n;
cin>>n;
input.resize(n);
for(int i=0;i<n;i++){
cin>>input[i].first>>input[i].second;
++input[i].first;
}
for(int i=1;i<=n;i++)
dp[i]={(int)1e18,(int)1e18};
int ans=1e18;
for(int i=0;i<n;i++){
for(int j=n;j>=0;j--){
int k=min(j+input[i].first,n);
if(dp[k].val>dp[j].val+input[i].second){
dp[k].val=dp[j].val+input[i].second;
dp[k].cnt=dp[j].cnt+1;
if(j+input[i].first>=n)
ans=min(ans,dp[k].val);
}
}
}
cout<<ans;
return 0;
}

浙公网安备 33010602011771号