自闭jpg. 就说说 PJ 吧。

TG炸的原因主要是因为PJ的炸裂以及T1……所以就直接分析根本原因了。

# 参考补题链接 #

# 推荐博客链接 #


0x00

考前一天晚上。

在LH巨佬家吃了饭,前往离HF大约1小时车程的NK边上的酒店。

到酒店收拾了一会儿,制订了个小计划,复习了不少板子。

像最短路,RMQ,LCA,EXGCD,euler啥的,都过了遍手。

当晚心态还是比较稳的,期待。

考试早上。

跟着大部队朦朦胧胧地到了NK门口。但好像一到门口就来精神了(?

然后在金牌讲师的带领下拍了OI生涯第一张比赛集体照。

接下来就在操场上等着进考场呗,期间遇到了几个外校的熟人,寒暄了几句。

进考场。

场地布置有点像ACM。

我还特别的注意到了以一种奇怪的方式折叠在天花板上的篮球框。

键盘,机器都还挺顺手的,不过座位刚好对着一条桌子腿,不是很舒服。

然后在裁判员宣读考试注意事项的时候,重新在脑袋里幻灯片了一下考试策略。(是的,我后面想起我考前还想过这玩意的


0x01

赛中。

T1一如既往的水。就直接每次暴力跑比n小的最大的二次幂即可。

5分钟打完调完过掉大样例跑去看T2。

T2就很迷惑了,想了半天只想出一个插排解法,心态直接就炸掉。但没办法,只能打完插排去看后面的题。一切炸的开始。

插排思路: 每次更新时二分找到之前的第i个位置,满足 a[i - 1] < x < a[i],将其插入,时间复杂度:你以为是 \(O(nlog_n)\) ?hhhhhh其实是 \(O(n^2)\)

T3感觉不可做,放掉,看T4。

T4第一眼好熟悉!马上反应是道dp,乱推了一堆通过单个二维转移的方程,没解出来。左看右看,考虑是不是最短路,结果直接随手把自己hack掉。最后打了个爆搜走人(我当时降智到直接没考虑记忆化。

再回去看T3,以为正解就是个暴力,后缀表达式乱搞交掉。

又跑去看T4,慌得要死,一直推到结束都没推出来。

最后五分钟T1刷了一个样例,感觉自己打错了,但其实是对的。于是魔改了一下,导致一中午都在担心自己好像没保存。

赛后。

一出考场就想起T4第二维两个循环转移。

一出考场就想起T2直接桶。。。(LH打树状数组过了,JC打对顶堆过了。

我谔谔,这次主要是心态炸锅了,太紧张了,导致一些白菜题没有切掉。

当然,后来反思也有考试策略有问题的成分。

估分:\(100\) \(+\) \(85\) \(+\) \(30\) \(+\) \(20\) \(=\) \(235\)。

实际能力极限:\(100\) \(+\) \(100\) \(+\) \(30\) \(+\) \(100\) \(=\) \(330\)。

以后做题还是应该再踏实一点,多做做思维题。

唉,好好复习NOIP吧。


0x02

题解部分

T1: (不再赘述。

#include <cstdio>

const int MAXN = 1e6 + 5;
int ans[MAXN], len = 0; int main() {
int n;
scanf ("%d", &n);
while(n) {
if(n == 1) {
printf("-1");
return 0;
}
long long t = 1;
while(t <= n)
t <<= 1;
if(t > n)
t >>= 1;
n -= t;
ans[++len] = t;
}
for(int i = 1; i < len; i++)
printf("%d ", ans[i]);
printf("%d", ans[len]);
return 0;
}

T2: (数据只到600?那毋庸置疑是个桶a。不要像我那样没看到600,导致只打了插排。

每次更新新的分数的时候,累加相对应的桶。

然后每次查找的时候,从大往小暴力找,找到分数线的位置直接输出即可。

时间复杂度:\(O(600n)\)

#include <cstdio>

inline int Max(int x, int y) {return x > y ? x : y;}
const int MAXN = 1e5 + 5;
const int MAXT = 605;
int a[MAXN], t[MAXT]; int main() {
int n, w;
scanf ("%d %d", &n, &w);
for(int i = 1; i <= n; i++) {
int x;
scanf ("%d", &x);
t[x]++;
int index = Max(1, i * w / 100), tot = 0, res = 0;
for(int j = 600; j >= 0; j--) {
tot += t[j];
if(tot >= index) {
res = j;
break;
}
}
printf("%d ", res);
}
return 0;
}

T3:(其实也不难想哦 可我还是不会

暴力就不提了吧。栈乱搞有30pt。个人认为这应该是最难的一道了。

至于正解,我们引入一个奇怪的字符树。

首先,你会发现整个表达式的取值只和一些特定的值有关,比如:

1 | (……) = 1;

0 & (……) = 0.

那么根据这个思路我们就可以考虑建树了嘛。实现看码。

时间复杂度:或许是 \(O(n + q)\) 吧。

#include <cstdio>
#include <stack>
#include <cstring>
using namespace std; const int MAXN = 1e6 + 5;
int a[MAXN], len = 0;
// a[]一组多用,下标 1 ~ n 为数集,n ~ 为符号集。
int cnt[MAXN], t[MAXN][2], Index = 0, n = 0;
// cnt-方便输入的数组,t 树,index 输入建树的下标。
bool vis[MAXN], q[MAXN];
// vis 表示这个数是否会决定表达式的答案,q 表示取反标记。
// vis 中,true 表示它不是决定性的,false 表示是决定性的。
char s[MAXN]; int dfs(int u, int f) {
// 在建树过程中顺便算出初始表达式的值。
// u 表示遍历,f 表示遍历时的取反标记。
a[u] ^= f; // 取反。
if(u <= n)
return a[u]; // 如果属于数集直接返回。
a[u] ^= f;
// 如果不属于数集,先取反回来,进行字符操作。
int x = dfs(t[u][0], (f ^ q[t[u][0]]));
int y = dfs(t[u][1], (f ^ q[t[u][1]]));
// 左右儿子遍历。
if(a[u] == -2) { // 如果是 &。
if(x == 0)
vis[t[u][1]] = 1;
if(y == 0)
vis[t[u][0]] = 1;
int res = (x & y);
return res;
}
else { // 如果是 |。
if(x == 1)
vis[t[u][1]] = 1;
if(y == 1)
vis[t[u][0]] = 1;
int res = (x | y);
return res;
}
} void update(int u) {
// 再扫一遍树。
// 我们之前只考虑了每个点的决定性情况。
// 但实际还应该考虑它的子树的决定性情况。
if (u <= n) return;
vis[t[u][0]] |= vis[u];
vis[t[u][1]] |= vis[u];
update(t[u][0]);
update(t[u][1]);
} int main() {
while(1) {
scanf ("%s", s);
if(s[0] >= '0' && s[0] <= '9') {
for(int i = 0; i < strlen(s); i++)
n = (n << 3) + (n << 1) + s[i] - '0';
break;
}
if(s[0] == 'x') {
int x = 0;
for(int i = 1; i < strlen(s); i++)
x = (x << 3) + (x << 1) + s[i] - '0';
cnt[++len] = x;
}
else if(s[0] == '|')
cnt[++len] = -1;
else if(s[0] == '&')
cnt[++len] = -2;
else if(s[0] == '!')
cnt[++len] = -3;
}
// 输入与一些保存方式。
Index = n;
for(int i = 1; i <= n; i++)
scanf ("%d", &a[i]);
stack<int> num;
// 后缀表达式-数字栈。
for(int i = 1; i <= len; i++) {
if(cnt[i] >= 0) { // 是数字。
num.push(cnt[i]);
continue;
}
switch(cnt[i]) {
case -1: { // 是 |。
int x = num.top();
num.pop();
int y = num.top();
num.pop();
Index++;
num.push(Index);
a[Index] = -1;
t[Index][0] = x;
t[Index][1] = y;
break;
}
case -2: { // 是 &。
int x = num.top();
num.pop();
int y = num.top();
num.pop();
Index++;
num.push(Index);
a[Index] = -2;
t[Index][0] = x;
t[Index][1] = y;
break;
}
case -3: { // 是 !。
q[num.top()] ^= 1;
break;
}
}
}
int Q, ans = dfs(Index, q[Index]);
update(Index);
scanf ("%d", &Q);
for(int i = 1; i <= Q; i++) {
int x;
scanf ("%d", &x);
printf("%d\n", vis[x] ? ans : (!ans));
}
return 0;
}

T4:(考场上降智了

一个数字三角形的变种。

其实就是需要多考虑一个从下往上走的情况,那就开两个dp更新嘛。

  • dp[i][j][1] 表示从下往上或从左往右走到 (i, j);
  • dp[i][j][0] 表示从上往下或从左往右走到 (i, j)。

这里指的是从上一步到这一步的状态。显然,答案就在 Max(dp[i][j][0], dp[i][j][1]) 里面。

然后就用类数字三角形的思路跑即可。

时间复杂度:\(O(nm)\)

#include <cstdio>
#include <cstring>
using namespace std; typedef long long LL;
inline LL Max(LL x, LL y) {return x > y ? x : y;}
const int MAXN = 1005;
const int INF = 0x3f3f3f3f;
LL dp[MAXN][MAXN][2];
int a[MAXN][MAXN]; int main() {
int n, m;
scanf ("%d %d", &n, &m);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
scanf ("%d", &a[i][j]);
memset(dp, -INF, sizeof dp);
dp[1][0][0] = 0;
for(int j = 1; j <= m; j++) {
for(int i = 1; i <= n; i++)
dp[i][j][0] = Max(dp[i - 1][j][0], Max(dp[i][j - 1][1], dp[i][j - 1][0])) + a[i][j];
for(int i = n; i >= 1; i--)
dp[i][j][1] = Max(dp[i + 1][j][1], Max(dp[i][j - 1][1], dp[i][j - 1][0])) + a[i][j];
// 因为不能重复走所以 dp[i][j][0] 不能被 dp[i - 1][j][1] 更新,同理 dp[i][j][1] 不能被 dp[i + 1][j][0]更新。
// 那么就只需要将走到左边点的最优解与上面或下面可以用于更新的最优解比最大即可。
}
printf("%lld\n", dp[n][m][0]);
return 0;
}

就当是重新回到起跑线上,凡是过去,皆为序章。

CSP.2020的更多相关文章

  1. 【初赛】CSP 2020 第一轮(初赛)模拟记录

    感觉初赛不过关,洛谷上找了一套没做过的来练习. 顺便写了详细的题解. 试题用时:1h 单项选择: 第 1 题 十进制数 114 的相反数的 8 位二进制补码是: A.10001110 B.100011 ...

  2. 日记 + sb错误

    置顶消息cpdd 1.29 完了,文化课没了 我是废物 1.28 更新了自己的副标题 前副标题:Future never has to do with past time,but present ti ...

  3. Solution Set - 神奇 NOIP 模拟赛

    \[\mathfrak{\text{Defining }\LaTeX\text{ macros...}}\newcommand{\vct}[1]{\boldsymbol{#1}}\newcommand ...

  4. [游记]2020/CSP - S总结

    2020 / C S P − S 总 结 2020/CSP - S总结 2020/CSP−S总结 这年的 C S P CSP CSP考的不是很理想,本来稳进的 C S P − J CSP-J CSP− ...

  5. 2020 CSP&NOIP 游记

    CSP初赛 CSP初赛 Day -1 早上打了模拟赛,T2寒假正好做过,然而还是还是被踩Orz,郑外NB!.中午出校吃了大盘鸡和拉面,还带回来了三瓶可乐. 初赛知识点看了两页不(看)想(不)看(懂)了 ...

  6. CSP/S 2020 退役记

    上一次的AFO记 上上次的AFO记 Day -INF 一条咸鱼的垂死挣扎. RP+=INF Day 0 出发辣. 早上来到机房,带上了准备的面包和泡面....然而后来嫌太占地方就没拿...草了. 而且 ...

  7. CSP初赛复习

    初赛复习 初赛一定要过啊,否则付出的那么多都白搭了! while(1) ++csp.rp,++csp.luck,++csp.scores; 历史 2020年开始,除NOIP以外的NOI系列其他赛事(包 ...

  8. Spring Cloud--尚硅谷2020最新版

    Spring Cloud 初识Spring Cloud与微服务 在传统的软件架构中,我们通常采用的是单体应用来构建一个系统,一个单体应用糅合了各种业务模块.起初在业务规模不是很大的情况下,对于单体应用 ...

  9. NOIP 2020 游记

    第一次写比赛游记,请多多指教! I. 考前 由于最近参加了太多太多比赛了,所以没有敲模板题: 考前一周:主要是在做 AtCoder 的题和 xjoi 的模拟赛,相当于恶补了一些套路吧! 考前一天:上午 ...

随机推荐

  1. sql中的字符串拼接

    转载自:https://www.cnblogs.com/rainman/p/6203065.html 1. 概述 在SQL语句中经常需要进行字符串拼接,以sqlserver,oracle,mysql三 ...

  2. C#+Arduino Uno 实现声控系统完全实施手册

    话不多说先上视频,一看就懂 另外可参考这里:https://www.cnblogs.com/dehai/p/4285749.html ,这个近6年前的帖子 程序结构 程序分成上位机(PC端)与下位机( ...

  3. System.Net邮件发送功能踩过的坑

    System.Net邮件发送功能踩过的坑 目录 System.Net邮件发送功能踩过的坑 1.EazyEmail邮件发送类库 2.邮件发送授权码与邮件密码 3.通过邮件密码来发送邮件 4.Wiresh ...

  4. VS中Dev控件在工具箱里的不见的解决办法

    出现问题:调整了VS中Dev控件后(以免生成程序每次都要在客户机上面注册dev),之前安装的DEV控件在vs工具箱中消失了,重装可以解决,但是太费时间了,检测dev自带的设置,找到了解决办法. 解决办 ...

  5. npm pm2

    安装 npm install -g pm2 用法 $ npm install pm2 -g # 命令行安装 pm2 $ pm2 start app.js -i 4 # 后台运行pm2,启动4个app. ...

  6. java enum 枚举值

    public enum PieChartEnum { PIE00("pie00"), PIE10("pie10"), PIE11("pie11&quo ...

  7. 【日拱一卒】链表——如何实现lru

    LRU Redis的内存淘汰机制好几种,如ttl.random.lru. lru(less recently used)即最近最少使用策略,表示在最近一段时间内最少被使用到的Redis键,如果遇到内存 ...

  8. SpringBoot中的响应式web应用

    目录 简介 Reactive in Spring 注解方式使用WebFlux 编程方式使用webFlux Spring WebFlux的测试 总结 简介 在Spring 5中,Spring MVC引入 ...

  9. TypeScript注意

    中文文档中,元组目前已经不能越界访问

  10. 【JVM第六篇--对象】对象的实例化、内存布局和访问定位

    写在前面的话:本文是在观看尚硅谷JVM教程后,整理的学习笔记.其观看地址如下:尚硅谷2020最新版宋红康JVM教程 一.对象的实例化 在平常写代码的过程中,我们用class关键字定义的类只是一个类的模 ...