当前位置: 代码迷 >> 综合 >> 大一上第十三周学习笔记
  详细解决方案

大一上第十三周学习笔记

热度:80   发布时间:2023-09-20 17:52:18.0

上周的D题一直WA。看来我还是有点菜

立个flag,这周五套cfabc题

这就是这周的目标

冲冲冲

 

12.7周一

 

Codeforces Round #688 (Div. 2)

A. Cancel the Trains

#include<bits/stdc++.h>
#define REP(i, a, b) for(int i = (a); i < (b); i++)
#define _for(i, a, b) for(int i = (a); i <= (b); i++)
using namespace std;const int MAXN = 110;
int a[MAXN];int main()
{int T; scanf("%d", &T);while(T--){memset(a, 0, sizeof(a));int n, m, x;scanf("%d%d", &n, &m);int ans = 0;_for(i, 1, n){scanf("%d", &x);a[x] = 1;	}	_for(i, 1, m){scanf("%d", &x);if(a[x]) ans++;}printf("%d\n", ans);} return 0;
} 

B. Suffix Operations

这题卡了我好久

关键是意识到一点,对于当前的一个数,只要求通过加减和前一个数一样大就行

至于改变哪一个数,需要比较改变每一个数所造成的影响,选择影响最优的那个

#include<bits/stdc++.h>
#define REP(i, a, b) for(int i = (a); i < (b); i++)
#define _for(i, a, b) for(int i = (a); i <= (b); i++)
using namespace std;const int MAXN = 2e5 + 10;
int a[MAXN], n;int main()
{int T; scanf("%d", &T);while(T--){scanf("%d", &n);_for(i, 1, n) scanf("%d", &a[i]);long long sum = 0;int key = 0;_for(i, 1, n - 1){sum += abs(a[i] - a[i+1]);if(i == 1) key = max(key, abs(a[i] - a[i+1]));else{int t = abs(a[i] - a[i+1]) + abs(a[i] - a[i-1]);int now = abs(a[i+1] - a[i-1]);key = max(key, t - now);}}key = max(key, abs(a[n-1] - a[n]));printf("%lld\n", sum - key);} return 0;
} 

C题没做出来,有点菜

 

接下来计划有变

把周训复习一遍,确保百分百掌握

考前可以打一下比赛找状态

 

12.8周二

今天复习了并查集

还是比较熟练的,题目比较简单,就不写到这了

复习了有向树,注意和无向树的区别

 

12.9周三

复习常用字符串函数

atoi atof stdlib.h
strcpy strncpy (只覆盖前几位)
strcat strncat
strcmp

 

12.11 周五

三分查找

学算法要理解本质才好记忆

比如三分算法

可以用来求单峰函数极值

知道L,R后让L,R不断靠近直到达到峰值

那么方法就是三分,算出lmid,rmid

这时要不l = lmid,要不r = rmid来缩小范围

当lmid,rmid在极值两侧时两种操作都可以

但是在同一侧时就不一样了,根据实际情况可以判断出是l更新还是r更新

理解本质就不难了

前缀和与差分

二维差分模仿一维差分

ai - ai-1

axy - ax-1y - axy-1 + ax-1y-1

 

除法取模:逆元

当结果要取模时,加减乘都可以直接在中间过程取模,而除法则要用逆元
逆元可以解决(a/b)%p的问题
转化为a * b^-1 % p
逆元相当于同余下的倒数
a的逆元记为a的负一次方
两者相乘在同余下为1

逆元怎么求呢
费马小定理
a^p-1 = 1
条件是p为质数且a,p互质
那么此时a的逆元就是a^p-2
p太大可以用快速幂求

 

快速乘

a * b % p当a * b爆long long时怎么办
类似快速幂的思想,可以把b看成二进制,拆开来和a乘

 

离校赛还有9天

校赛前来5套abc题

加油

 

12.12 周六

Codeforces Round #687

赛前第一套cf题目

A. Prison Break

写完看了题解,我写的稍微复杂了一点,不过过了就行

#include<bits/stdc++.h>
#define REP(i, a, b) for(int i = (a); i < (b); i++) 
#define _for(i, a, b) for(int i = (a); i <= (b); i++) 
using namespace std;int n, m, r, c;int cal(int x, int y)
{return abs(x - r) + abs(y - c); 
}int main()
{int T; scanf("%d", &T);while(T--){scanf("%d%d%d%d", &n, &m, &r, &c);int ans = 0;ans = max(ans, cal(1, 1));ans = max(ans, cal(n, m));ans = max(ans, cal(1, m));ans = max(ans, cal(n, 1));printf("%d\n", ans);}return 0;
}

B. Repainting Street

我很快就想到了确定了颜色之后贪心就好

那么就想到每种颜色都试一遍,但觉得会超时

其实不会超时,因为我漏看了c<=100这个条件,算一下一千万不会超

复杂度是n*max(c)

没看清题目,于是我就想了一个O(n)的算法

这个算法搞了我好久,最后还是写出来了。反正写题就是锻炼思维嘛

但最后我发现我写的比n*max(c)的时间还长。应该是我写的常数大一些

 

O(n)

#include<bits/stdc++.h>
#define REP(i, a, b) for(int i = (a); i < (b); i++) 
#define _for(i, a, b) for(int i = (a); i <= (b); i++) 
using namespace std;const int MAXN = 1e5 + 10;
int a[MAXN], cnt[MAXN], pre[MAXN], n, k;int cal(int x)
{if(x <= 0) return 0;if(x % k == 0) return x / k;return x / k + 1;
}int main()
{int T; scanf("%d", &T);while(T--){memset(cnt, 0, sizeof(cnt));memset(pre, 0, sizeof(pre));scanf("%d%d", &n, &k);int m = 0;_for(i, 1, n){scanf("%d", &a[i]);m = max(a[i], m);if(i == 1) continue;if(a[i] != a[i-1]){pre[a[i-1]] = max(pre[a[i-1]], i - 1);int len = i - pre[a[i]] - 1;if(len <= 0) continue;if(len % k == 0) cnt[a[i]] += len / k;else {cnt[a[i]] += len / k + 1;pre[a[i]] = min(n, pre[a[i]] + (len / k + 1) * k);}}	} pre[a[n]] = n;int ans = 1e9;_for(i, 1, m) {cnt[i] += cal(n + 1 - pre[i] - 1);ans = min(ans, cnt[i]);}printf("%d\n", ans);}return 0;
}

O(n * max(c))

#include<bits/stdc++.h>
#define REP(i, a, b) for(int i = (a); i < (b); i++) 
#define _for(i, a, b) for(int i = (a); i <= (b); i++) 
using namespace std;const int MAXN = 1e5 + 10;
int a[MAXN], n, k;int main()
{int T; scanf("%d", &T);while(T--){scanf("%d%d", &n, &k);int m = 0; _for(i, 1, n) {scanf("%d", &a[i]);m = max(m, a[i]);} int ans = 1e9;_for(color, 1, m){int res = 0, p = 1;while(p <= n){if(a[p] != color){res++;p += k;}else p++;}ans = min(ans, res); }printf("%d\n", ans);}return 0;
}

 

C. Bouncing Ball

简单的线性dp。注意几个点

一.初始化最大用0x3f(后来发现不需要初始化)

二.一个数字输入可以用%1d

三.这题的关键是理解去掉首元素然后序号改变的意义。

可以一开始先做这个操作,把所有起点可能的情况初始化一下

题目说了不能少于p个元素,以为有什么坑,后来发现不影响做题,总之就是最少要跳一下

#include<bits/stdc++.h>
#define REP(i, a, b) for(int i = (a); i < (b); i++) 
#define _for(i, a, b) for(int i = (a); i <= (b); i++) 
using namespace std;const int MAXN = 1e5 + 10;
int a[MAXN], dp[MAXN], n, p, k, x, y;int main()
{int T; scanf("%d", &T);while(T--){scanf("%d%d%d", &n, &p, &k);_for(i, 1, n) scanf("%1d", &a[i]);scanf("%d%d", &x, &y);int ans = 1e9;_for(i, p, n) dp[i] = (i - p) * y + (a[i] == 0) * x;_for(i, p, n){if(i >= p + k) dp[i] = min(dp[i], dp[i - k] + x * (a[i] == 0));if(i + k > n) ans = min(ans, dp[i]);}printf("%d\n", ans);}return 0;
}

 

现在的目标就是abc能比较快的熟练的做出来

后面再刚第四题

 

12.13 周日

Codeforces Round #689

赛前第二套cf题

提升实力秘诀就是:独立思考(不轻易看题解)+多做题

 

A. String Generation

#include<bits/stdc++.h>
#define REP(i, a, b) for(int i = (a); i < (b); i++) 
#define _for(i, a, b) for(int i = (a); i <= (b); i++) 
using namespace std;char ch[] = {'a', 'b', 'c'};int main()
{int T; scanf("%d", &T);while(T--){int n, k, p = 0;scanf("%d%d", &n, &k);while(n > 0){if(n >= k){_for(i, 1, k) putchar(ch[p]);n -= k;p = (p + 1) % 3;}else{while(n--){putchar(ch[p]);p = (p + 1) % 3;}}}puts("");}return 0;
}

B. Find the Spruce

直接暴力n的四次方

这题的关键点就是初始化前缀和可以省去一维循环,变成n的三次方

#include<bits/stdc++.h>
#define REP(i, a, b) for(int i = (a); i < (b); i++) 
#define _for(i, a, b) for(int i = (a); i <= (b); i++) 
using namespace std;const int MAXN = 500 + 10;
char s[MAXN][MAXN];
int sum[MAXN][MAXN], n, m;int cal(int x, int y)
{_for(i, 1, n){if(x + i - 1 > n || y - i + 1 < 1 || y + i - 1 > m ) return i - 1;if(sum[x+i-1][y+i-1] - sum[x+i-1][y-i] != 2 * i - 1)return i - 1;}return n;
}int main()
{int T; scanf("%d", &T);while(T--){scanf("%d%d", &n, &m);_for(i, 1, n) scanf("%s", s[i] + 1);_for(i, 1, n)_for(j, 1, m)sum[i][j] = sum[i][j-1] + (s[i][j] == '*');int ans = 0;_for(i, 1, n)_for(j, 1, m)ans += cal(i, j);printf("%d\n", ans);}return 0;
}

C. Random Events

这题的思路很快

首先发现各个操作独立,然后发现有一些操作根本成不成功对答案没有影响(把样例手算一遍可以提供思路)

然后注意要特判一下,我特判的时候直接把后面的输入也省去了,这个低级错误卡了我好久,以后注意

#include<bits/stdc++.h>
#define REP(i, a, b) for(int i = (a); i < (b); i++) 
#define _for(i, a, b) for(int i = (a); i <= (b); i++) 
using namespace std;const int MAXN = 1e5 + 10;
int a[MAXN], n, m;int main()
{int T; scanf("%d", &T);while(T--){scanf("%d%d", &n, &m);_for(i, 1, n) scanf("%d", &a[i]);int p = 1;for(int i = n; i >= 1; i--)if(a[i] != i){p = i;break;}double t = 1;while(m--){int x; double y;scanf("%d%lf", &x, &y);if(x >= p) t *= (1 - y);}if(p == 1) puts("1.000000");else printf("%.6f\n", 1 - t);}return 0;
}

 

Codeforces Round #685 (Div. 2)

赛前第3套abc

A. Subtract or Divide

#include<bits/stdc++.h>
#define REP(i, a, b) for(int i = (a); i < (b); i++) 
#define _for(i, a, b) for(int i = (a); i <= (b); i++) 
using namespace std;int main()
{int T; scanf("%d", &T);while(T--){int n; scanf("%d", &n);if(n <= 3) printf("%d\n", n - 1);else printf("%d\n", (n & 1) + 2);}return 0;
}

B. Non-Substring Subsequence

一开始就有种想法是直接从原串上改,也就是把两边其中一边的元素移到远处

但不知道这样做对不对,不知道这样能不能覆盖所有情况

后来想通了如果这样都找不到,那就一定找不到

#include<bits/stdc++.h>
#define REP(i, a, b) for(int i = (a); i < (b); i++)
#define _for(i, a, b) for(int i = (a); i <= (b); i++)
using namespace std;const int MAXN = 100 + 10;
int a[MAXN], n, q;int main()
{int T; scanf("%d", &T);while(T--){scanf("%d%d", &n, &q);_for(i, 1, n) scanf("%1d", &a[i]);while(q--){int l, r;scanf("%d%d", &l, &r);int ans = 0;_for(i, 1, l - 1)if(a[i] == a[l]){ans = 1;break;}_for(i, r + 1, n)if(a[i] == a[r]){ans = 1;break;}if(ans) puts("YES");else puts("NO");}}return 0;
}

 

现在做思维题还是有点慢

没有什么捷径

打cf,补题,打cf,补题

一直刷一直刷,独立思考

一直做比自己水平高一些的题目,一直刷一直刷

  相关解决方案