2022-7-16
T1:取餐码
- 妥妥军哥送温暖,裸的筛法,埃氏筛 ( n log log ( n ) ) (n\log\log(n)) (nloglog(n))线性筛 ( n ) (n) (n)都能过。
T2:堆人塔
- 类似于分治,目标是静态求几个区间的最大值,又是一个很直接的题,很容易意识到用st表和线段树,但,线段树没学,st表又忘得差不多了-_-最后只能dfs暴力枚举每个区间(没A还是我菜)
T3:钦定IOI选手
- 目标:动态维护一个区间的中位数,有些人用优先队列——堆,写了个对顶堆来维护,却只拿了20(堆的插入,弹出均为 O ( log ( n ) O(\log(n) O(log(n))),正解:二分中位数x,那么怎么判断呢?很简单,思考一下,我们的目标是判断x左右大于它和小于它的值要相等所以我们可以针对每一个x建立一个新的数组,让原数组大于x的变为1小于的变为-1,再处理一个累加和数组,就可以判断是否为中位数以及如何左右移动。
bool check(int x) {
for(int i = 1; i <= n; i ++) {
if(a[i] >= x) b[i] = 1;
else b[i] = -1;
sum[i] = sum[i - 1] + b[i];
}
int minn = 1e9;
for(int i = k; i <= n; i ++) {
minn = min(minn, sum[i - k]);
if(sum[i] - minn > 0) return 1;
}
return 0;
}
- 这是一个很常用的统计方法,将绝对大小变为相对大小,在下面的题中我们还将见到。
T4:攻打恶魔之巅
- 正解:分层图最短路,将每个传送门建图。
- 还有一种方法DP!这个很容易想到,用走和不走传送门去更新最优值,但dp的细节很多,例如最外层循环是宝石的个数,而且要从前往后,从后往前走两边,因为题目并没有说不可以往后跳(可怜的czy)
- 这道题还有一种做法0/1bfs,bfs的一个特殊情况,指边只有0,和1两种状态,对于本题走传送门是0,直接走就是1,满足0/1bfs.
2022-7-17
T1:你们必须要分开
- 今天的题含蓄了很多,3道思维题,就一道算法题,例如本题,就是一道找规律的题,而且要自己手构数据去猜结论,直接暴力绝对是不理智的,多想想就能多拿分
T2:J市里走一走
- (题意搞错了,直接挂了#_#)暴力的计算是拿不了高分的,要去画图,找规律,推结论,找最优的计算方法。
T3:玩树
- 稍加思考不难发现,前序遍历是满足dfs的,所以问题就简单了,贪心,每次都走最小的字树就能保证输出的前序遍历字典序最小,关键在于如何在链式前向星中排序,其实我们仔细思考一下,我们是不是可以在建边之前排序,排好序后再有序建边,没错这是正解思想之一,还有一种复杂的——先建边复制一遍,排序,在更新一下。总之,这道题一旦发现满足dfs后,就是送。
T4:玩数列
- 唯一的算法题,数据良心,求一个数,xor上一个数列使得这个序列的逆序对对数最小,先考虑暴力,先在输入找到序列最大值x,则这个最优的数一定小于x,理由,考虑二进制,大于x的数二进制一定长于x,所以当异或比x大的值序列的相对大小一定不变,所以对逆序对没有影响,再考虑如何求逆序对,比较暴力的做法——树状数组,归并排序(最后一步复制错位了,挂了-_-就差一点60)
- 复杂度有点高,考虑如何优化,算法上已经到天花板了,那我们就考虑一下数据结构,看到位运算,不难想到0/1tire树,所以将每个数插入0/1tire根据0/1tire的性质找每一位(二进制下)1和0的个数来判断逆序对,倒推出最优的数;
2022-7-18
T1:我们就偏不分开
- (哈哈哈。,上一道题的后续,老师也太有趣了_)T1是一道思维题;分数给的很良心,双层循环暴力就能拿到60,满分也只需要用map+前缀和标记就可以了
- 考场上思考了大概10分钟我想到用前缀和去维护区间值,由day1的t3,我们可以想到:将上移,左移标记为正操作,下移右移标记为负操作,最后判断是否为0,但面前有个问题:如果以相同的值去操作当面对上移右移就会误判为0,于是我就进一步去想,用两个前缀和去共同维护当他们都为0就让ans++。当然了这个思路也只是第二档分,挂了。
T2: 字典序
- 题目很长,输入就有很多行,而且题意十分复杂,分数分档挺多的,当时看完题人
都傻了:这咋写?正解是一个复杂的分层图,最后不死心,看看数据发现一位特殊数据————最短路,思考一下,考场上我用了SPFA特殊样例过了,但是呢,考完就爆蛋了,SPFA挂了,同学的堆优化dij拿到了应得的7分。
T3:电梯
- 看到这一题我内心是崩溃的,虽然题面很简单,但根本不知道用什么方式去写这道题,最后不得不写了份模拟,(拿了10分还是样例分)正解:记忆化搜索+优化过后的DP
T4:追杀
- t4真心不难,要不是时间不够我也不会只拿30分,判环是一个很精妙的思路,这个很容易想到,类似一个记忆化搜索吧,
O
(
n
2
)
O(n^2)
O(n2)预处理,
O
(
1
)
O(1)
O(1)回答,
用LCM的思路去想,倍增处理秒数,比正解跑的还快。
总结:
- 考场策略:
- 不要被题目的顺序所迷惑,先浏览所有题,挑自己拿手或熟悉的题目先做,后做拿不准的题或不会的题,
- 不能放弃,挑最有把握的题想,多想,去思考,csp-j/s没有一道题是马上就能想到的,用你的学过的知识去试。
- 对于一道题已经写了很久(40分钟)如果真的想不出来,可以适当跳过,
放弃梦想苟起来。 - 写完一道题要进行检查,例如自己出一组数据看看输出结果,或者打个表,看和自己预料的是否相同,(今天T1差点连60分都没拿到)
- 暴力打满,写暴力也是有策略的,写暴力前也是要思考,论证的,还可以尝试分段——对于不同的档位进行不同的暴力/贪心有时也会出奇迹,
- 码代码时也要格外小心,因为考场调代码确实是一件很蠢的事,但如果真的避免不了,有以下建议
如何调?我常用三种方法;
1.直接看代码,寻找语句中逻辑错误,或者操作失误得到的错误,但绝不是从头开始看,而是挑选怀疑的地方着重看,
2.调试,用c++自带的debug,当然,debug前也要选取关键的值,不要同时关注太多的信息,最好debug前先手推一个方便比较。同时注意!c++的debug是从c迭代过来的,所以debug不适用于stl,甚至有时c++甚至会直接崩溃!
3.打表,最直接,最便捷,最快速,和debug同理,也要选取关键的值,打表前先手推一个。
我个人最常用打表,快,准 (当然,所有调试都建立在你的思路,算法无误的前提下)
- 如果连调试也救不了你了,就在平时多刷题,累积( ∏ \prod ∏)码力,逻辑思考能力。