T1 决斗

签到题,考场上10min就做出来了。

我的方法是排序之后贪心打怪,就是用尽量小的怪去打现在场上最小的怪。用一个同侧双指针实现。 \(O(nlogn)\)。

另一种方法注意到了值域很小,可以放进桶里做到 \(O(n)\)。

还有一种方法。junjun大佬说答案就是出现次数最多的数的出现次数,感性理解一下也是对的。

#include<bits/stdc++.h>
#define F(i,l,r) for(int i(l);i<=(r);++i)
#define G(i,r,l) for(int i(r);i>=(l);--i)
using namespace std;
using ll = long long;
const int N = 1e5 + 5;
int a[N], n;
signed main(){
// freopen("duel.in","r",stdin);
// freopen("duel.out","w",stdout);
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin >> n;
F(i, 1, n) cin >> a[i];
sort(a + 1, a + n + 1);
int nw = 1, ans = n;
F(i, 2, n){
if(a[i] > a[nw]) -- ans, ++ nw;
}
cout << ans << '\n';
return 0;
}

T2 超速检测

第一问:算出每辆车超速的临界位置 \(x\),看一下超速区间里面有没有检测仪,有的话答案 +1。

如果 \(a_i \lt 0\),那么超速区间为 \([d[i], x]\)

如果 \(a_i \ge0\),那么超速区间为 \([x, p[m]]\)。

这里涉及到非常多令人作呕的上下取整问题,下来调了一个多小时……

第二问:把第一问里面有效的超速区间拿出来,问题模型就是:

选最少的特殊点,使得每个区间都包含至少一个特殊点。

考场上想到了二分+贪心,但最终坚定地选择了线段树(嘻嘻嘻……还没写出来,我是sb)

考场做法疑似 \(60 \sim 80pts\),哎我都不奢求什么了,希望 \(60\) 分保底顺利拿到……(考场上真是紧张坏了)

正解就是先给区间排序(以 \(l\) 为第一关键字,\(r\) 为第二关键字)然后贪心,由于 \(l\) 已经保证递增了,所以贪心的功夫全在 \(r\) 怎么处理上。

记 \(pmin\) 表示最新选择的点。发现一个性质:\(pmin\) 一定是尽量靠右的一个位置,因为这样的话,随着 \(l\) 增加, \(pmin\) 能被尽量多的区间包含。

只要 \(l_i \le pmin\),\(pmin\) 就可以一直产生贡献,并且如果 \(r_i \lt pmin\),为了实际上真的把 \(i\) 区间装进来了,要将 \(pmin\) 更新为 \(r_i\)。

当 \(l_i \gt pmin\),我们就新开一个点,初始位置 \(pmin = r_i\)。

画两个图玩一下,发现很对。(嘻嘻……

思路就是这样。

自己感觉难点一方面是要往简单想,既然一开始有贪心的想法,为什么不先试着多玩两个图甚至码一下呢?

另一方面就是第一问细节是真多,要套公式,同时还要注意上下取整的问题。(如果写 \(nlogn\) 好像码起来会稍微容易一点)

值域较小,可以做到 \(O(Tn)\)。(其实我还是排了个序)

#include<bits/stdc++.h>
#define F(i,l,r) for(int i(l);i<=(r);++i)
#define G(i,r,l) for(int i(r);i>=(l);--i)
using namespace std;
using ll = long long;
char buf[100], *p1 = buf, *p2 = buf;
inline int gc(){
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,100,stdin),p1==p2)?EOF:*p1++;
}
inline int rd(){
int x = 0; char ch; bool f = 1;
while(!isdigit(ch = gc())) f ^= (ch == '-');
do x = (x << 3) + (x << 1) + (ch ^ 48); while(isdigit(ch = gc()));
return f ? x : -x;
}
const int N = 1e5 + 5;
struct cat{
int l, r;
bool operator < (const cat &other)const{
return l == other.l ? r < other.r : l < other.l;
}
}e[N];
int T, n, m, L, o, cnt = 0;
int d[N], v[N], a[N], p[N];
int pos[1000006], s[1000006];
void init(){
n = rd(), m = rd(), L = rd(), v[0] = rd();
F(i, 1, n) d[i] = rd(), v[i] = rd(), a[i] = rd();
F(i, 1, m) p[i] = rd(), pos[p[i]] = i, s[p[i]] ++ ;
}
int tot = 0;
int solve1(){
int st = 1, ans1 = 0;
F(i, 1, L){
if(pos[i]){
F(j, st, i) pos[j] = pos[i];
st = i + 1;
}
s[i] += s[i - 1];
}
G(i, L, 1){
if(pos[i]) break;
pos[i] = m + 1;
}
F(i, 1, n){
ll x;
if(a[i] == 0){
if(v[i] <= v[0]) continue;
if(s[L] - s[d[i] - 1]){
e[++ cnt] = (cat){pos[d[i]], m};
++ ans1;
}
continue;
}
x = (1ll * v[0] * v[0] - 1ll * v[i] * v[i]) / (2ll * a[i]) + d[i];
if(a[i] > 0){
if(v[0] < v[i]){
if(s[L] - s[d[i] - 1]){
e[++ cnt] = (cat){pos[d[i]], m};
++ ans1;
}
}
else{
++ x; // begin to over
if(x > L) continue;
if(s[L] - s[x - 1]){
e[++ cnt] = (cat){pos[x], m};
++ ans1;
}
}
}
else{
if(v[i] <= v[0]) continue;
if((1ll * v[0] * v[0] - 1ll * v[i] * v[i]) % (2ll * a[i]) == 0) -- x; // end to over
if(x < d[i]) continue;
int l = pos[d[i]], r = pos[x + 1] - 1;
if(x >= L) x = L, r = m;
if(s[x] - s[d[i] - 1]){
e[++ cnt] = (cat){l, r};
++ ans1;
}
}
}
return ans1;
}
int solve2(){
sort(e + 1, e + cnt + 1);
int pmin = 0, ans2 = 0;
F(i, 1, cnt){
int l = e[i].l, r = e[i].r;
if(l > pmin){
++ ans2;
pmin = r;
}
else pmin = min(pmin, r);
}
return m - ans2;
}
signed main(){
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
T = rd();
while(T --){
init();
int ret1 = solve1(), ret2 = solve2();
printf("%d %d\n", ret1, ret2);
F(i, 0, L) pos[i] = s[i] = 0;
cnt = 0;
}
return 0;
}

T3 染色

\(O(n^2)\)

先考虑 \(O(n^2)\) 做法,记 \(f[i][1/0]\) 表示 \(i\) 的颜色和 \(i - 1\) 一样 / 不一样 的最大得分。

对于颜色一样,有:

\[f[i][1] = max(f[i - 1][1], f[i - 1][0]) + a[i]/0
\]

对于颜色不一样,我们需要在 \(1 \sim i - 1\) 中找一个位置 \(j\) 和 \(i\) 染成同种颜色,并且它们之间全是异色,形如:

\[1000\dots0001
\]

思考一下,会发现现在最大的问题是 \(j + 1\) 位置会和哪个位置匹配。转移可大致写为:

\[f[i][0] = \max_{1 \le j \le i - 2}max(f[j][0], f[j][1]) + val(j + 2, i - 1) + ?
\]

问号就是 \(j + 1\) 的贡献。难道为了这个地方我们又要多枚举一重循环?

这里有一个很逆天的 \(trick\),我们可以从 \(f[j + 1][0]\) 转移过来!

解释一下:回到定义,我们只规定颜色一不一样,没说到底谁0谁1,所以 \(f[j + 1][0]\) 就不用再考虑 \(j + 1\) 的贡献了,前面已经求出来了。

新的转移为:

\[f[i][0] = \max_{1 \le j \le i - 2} f[j + 1] + val(j + 2, i - 1) + a[i]/0
\]

\(val\) 可以前缀和预处理,于是就有了一个 \(O(n^2)\) 做法。

拆式子

加上前缀和后,式子可以写成:

\[f[i][0] = s[i - 1] + a[i] / 0 + \max_{1 \le j \le i - 2} f[j + 1] - s[j + 1]
\]

对于 \(\max\) 里面可以直接前缀最大值,记作 \(maxn\)。

对于 \(a[i]/0\),记 \(mx[a[i]]\) 表示

\[\max_{1 \le j \le i - 1 \cap a[j] = a[i]}f[j] - s[j] + a[i]
\]

所以 \(f[i][0] = \max(maxn, mx[a[i]] + s[i - 1])\)。

时间复杂度 \(O(Tn)\)。

#include<bits/stdc++.h>
#define F(i,l,r) for(int i(l);i<=(r);++i)
#define G(i,r,l) for(int i(r);i>=(l);--i)
using std::max;
using ll = long long;
char buf[100], *p1 = buf, *p2 = buf;
inline int gc(){ return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,100,stdin),p1==p2)?EOF:*p1++; }
inline int rd(){
int x = 0; char ch;
while(!isdigit(ch = gc()));
do x = (x << 3) + (x << 1) + (ch ^ 48); while(isdigit(ch = gc()));
return x;
}
const int N = 2e5 + 5;
const ll inf = 0x3f3f3f3f3f3f3f3f;
ll f[N][2], s[N], mx[1000006];
int n, T, a[N];
void init(){
n = rd(); int amax = 0;
F(i, 1, n) a[i] = rd(), amax = max(amax, a[i]);
F(i, 0, n) f[i][0] = f[i][1] = 0;
F(i, 0, amax) mx[i] = -inf;
s[0] = s[1] = 0; F(i, 2, n) s[i] = s[i - 1] + ((a[i] == a[i - 1]) ? a[i] : 0);
}
ll solve(){
ll maxn = 0;
F(i, 1, n){
f[i][1] = max(f[i - 1][1], f[i - 1][0]) + ((a[i] == a[i - 1]) ? a[i] : 0);
f[i][0] = s[i - 1] + maxn;
if(mx[a[i]] != -inf) f[i][0] = max(f[i][0], s[i - 1] + mx[a[i]]);
mx[a[i - 1]] = max(mx[a[i - 1]], f[i][0] - s[i] + a[i - 1]);
maxn = max(maxn, f[i][0] - s[i]);
} return max(f[n][0], f[n][1]);
}
signed main(){
T = rd(); while(T --) init(), printf("%lld\n", solve());
return fflush(0), fclose(stdin), fclose(stdout), 0;
}

总结

这次比赛让我意识到了 “策略” 和 “思维变现” 的重要性。

关于策略,错误地沿用了一贯打模拟赛时的策略,在 T1 切掉后没有选择先把题都读一遍然后找好拿的分先拿,而是选择硬刚 T2,打到 16:30 还是一分未拿直接慌了,4h 赛制和 4.5h 的实际感受完全不一样!

如果让我再决策一次,我会先通读题目,然后把 T2 60pts,T3 20 ~ 35pts 先写了(不是写完就至少180谁不心动?)然后我可能会开 T2 正解,也可能开 T3 50分,不好还原当时的心境……但这个时候再写 T2 也会淡定许多吧?T4那个暴力嘛,看最后时间够不够了。

关于思维变现,昨晚已和 lyy 深入交流过了(别人是物竞啊%%%)这次 T2 想过二分+贪心然后否了选择了线段树,写线段树又一直再自我怀疑;T3 一眼 dp 但慌乱之中没有心情也没有时间深入想下去。

我觉得有两点反思。

第一,肯定自己,思维肯定不差!这两天 “采访了” 机房很多同学,他们想到了的点,我也都想到了类似的。“伸脖子是一刀,缩脖子也是一刀”,要自信!

第二,矫正自己,现在最大的问题是 思维很活跃 但 变现到成绩上很少!要刷真题,刷好题,不断地去摸索什么难度的题一般 不会想什么,应该先想什么,哪些点子一定是不该出现在这个位置的题……只要你找到那条思维的主线,你的noip一定可以1=!

“新旧之间没有怨讼,唯有真与伪是大敌。”——柴静

CSPS2024题目总结的更多相关文章

  1. 谈谈一些有趣的CSS题目(十二)-- 你该知道的字体 font-family

    开本系列,谈谈一些有趣的 CSS 题目,题目类型天马行空,想到什么说什么,不仅为了拓宽一下解决问题的思路,更涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题 ...

  2. 谈谈一些有趣的CSS题目(十一)-- reset.css 知多少?

    开本系列,谈谈一些有趣的 CSS 题目,题目类型天马行空,想到什么说什么,不仅为了拓宽一下解决问题的思路,更涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题 ...

  3. 谈谈一些有趣的CSS题目(三)-- 层叠顺序与堆栈上下文知多少

    开本系列,讨论一些有趣的 CSS 题目,抛开实用性而言,一些题目为了拓宽一下解决问题的思路,此外,涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题中有你感觉 ...

  4. 一道返回num值的小题目

    题目描述: 实现fizzBuzz函数,参数num与返回值的关系如下: .如果num能同时被3和5整除,返回字符串fizzbuzz .如果num能被3整除,返回字符串fizz .如果num能被5整除,返 ...

  5. 谈谈一些有趣的CSS题目(一)-- 左边竖条的实现方法

    开本系列,讨论一些有趣的 CSS 题目,抛开实用性而言,一些题目为了拓宽一下解决问题的思路,此外,涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题中有你感觉 ...

  6. 谈谈一些有趣的CSS题目(二)-- 从条纹边框的实现谈盒子模型

    开本系列,讨论一些有趣的 CSS 题目,抛开实用性而言,一些题目为了拓宽一下解决问题的思路,此外,涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题中有你感觉 ...

  7. 谈谈一些有趣的CSS题目(四)-- 从倒影说起,谈谈 CSS 继承 inherit

    开本系列,讨论一些有趣的 CSS 题目,抛开实用性而言,一些题目为了拓宽一下解决问题的思路,此外,涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题中有你感觉 ...

  8. 谈谈一些有趣的CSS题目(五)-- 单行居中,两行居左,超过两行省略

    开本系列,讨论一些有趣的 CSS 题目,抛开实用性而言,一些题目为了拓宽一下解决问题的思路,此外,涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题中有你感觉 ...

  9. 谈谈一些有趣的CSS题目(六)-- 全兼容的多列均匀布局问题

    开本系列,谈谈一些有趣的 CSS 题目,题目类型天马行空,想到什么说什么,不仅为了拓宽一下解决问题的思路,更涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题 ...

  10. 谈谈一些有趣的CSS题目(七)-- 消失的边界线问题

    开本系列,谈谈一些有趣的 CSS 题目,题目类型天马行空,想到什么说什么,不仅为了拓宽一下解决问题的思路,更涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题 ...

随机推荐

  1. vue-表单与v-model

    使用 v-model 后,表羊控件显示的值只依赖所绑定的数据,不再关心初始化时的 value 属性,对于 textarea></textarea> 之间插入的值,也不会生效. 使用 ...

  2. 11-canvas绘制折线图

    1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="U ...

  3. 组长:你熟悉过React,开发个Next项目模板吧,我:怎么扯上关系的?

    组长:你熟悉过React,开发个Next项目模板吧,我:怎么扯上关系的? 最近工作安排我开发一个Next.js项目模板,心里默笑,React用得少得都快忘光了,现在得搞Next?虽然我曾是React的 ...

  4. 前后端分离使用mp遇到问题

    <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-s ...

  5. android java.lang.Exception: java.net.ProtocolException: Expected HTTP 101 response

    Android stomp长连接连接异常: 报错:java.lang.Exception: java.net.ProtocolException: Expected HTTP 101 response ...

  6. C++: 如何高效地往unordered_map中插入key-value

    C++: unordered_map 花式插入key-value的5种方式 前言 无意中发现std::unordered_map.std::map等插入key-value对在C++17后竟有了 ins ...

  7. RxJS 系列 – Scheduler

    前言 大部分情况下, RxJS 都是用来处理异步执行的. 比如 Ajax, EventListener 等等. 但其实, 它也是可以同步执行的, 甚至 by default 它就是同步执行的 (下面会 ...

  8. ASP.NET Core – MVC

    前言 在 ASP.NET Core – MVC vs Razor Page 里有提到 MVC. 它算是 WebAPI 的抽象. 但是通常 MVC 指的是比较传统的 Website, WebAPI 则是 ...

  9. Asp.net core 学习笔记 Secret 和 Data Protect Azure key-vault & Storage Account 第 2 篇

    更新 30-04-2023 最新版本请看这 2 篇 ASP.NET Core – User Secret & Azure Key Vault 之前有写过 2 篇关于 key-vault 和 d ...

  10. JavaScript——事件监听

    事件监听      1.事件绑定        2.常见事件