水题狂欢赛 (爬楼梯赛)题解(偏向自我反省)
前言
这真的是一套水题。(就初一秒切那种(xsc0laoer是巨佬,不算)),但是zyq依旧非常f**k
的去爬楼梯了。。。。
犯了各种奇奇怪怪的错误,题目看错,变量看错,改一点就可以让时间复杂度降次的优化发现不了,看到这套题水就想很快的A掉,完全不动脑筋,整个人都是浮躁的。
题易要犯错,题难不愿做,整个人特别浮躁,这一两周状态都特别差(喵喵喵 zyq状态好过吗)。心态都有点崩了。
考水题zyq还是爬楼梯去了,考CSP-2019
zyq 做到一半就去看《钢铁是怎样炼成的》去了。
没有办法沉下心来去想题,想半夜起床改代码结果一觉睡到天亮。。
笔者真的不是想在这里抱怨,真的不是想在在blog里散发负能量,只是想借着写这套水题题解的机会,说出自己长久以来的问题
尽管大家都A掉了这套题。很明显,这篇题解也不会有人认真去看,但是笔者还是想写一写这套让笔者爬楼梯的题的题解,以检查自己的思路是在什么地方卡住了。
废话就说到这儿了,勿以题难而不为 更勿以题易而不屑为。,与君共勉之。
T1 czq的集合差集
题目
思路
\(A \cap B \ a \cup B\)等价于a ^ b
代码
#include <cmath>
#include <cstdio>
#include <cstring>
using namespace std;
unsigned long long a, b;
int main() {
scanf("%llu %llu", &a, &b);
printf("%llu", a ^ b);
return 0;
}
T2 czq的原木种植
题目
思路
设:有两根木头\(a\), \(b\)
不妨设\(len_a > len_b\)
需要砍\(k\)长度的木条 \((k > lenb)\)
在\(a\)上砍后价值为 \((lena - k)^2 + lenb^2 = lena^2 + lenb^2 + lenc^2 - 2 \times k \times lena\)
砍\(b\)后为 \((lenb - k) ^ 2 + lena ^ 2 = lena^2 + lenb^2 + lenc^2 - 2 \times k \times lenb\)
又$\because lena > lenb $
\(\therefore (lena - k)^2 + lenb^2 < (lenb - k) ^ 2 + lena ^ 2\)
所以尽量找短的树砍,证毕
代码
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define int long long
using namespace std;
const int maxn = 1e5 + 5;
int n, k;
int a[maxn];
long long ans;
signed main() {
scanf("%lld %lld", &n, &k);
for(int i = 1; i <= n; i ++){
scanf("%d", &a[i]);
}
sort(a + 1, a + n + 1);
for(int i = 1; i <= n; i ++){
if(k > a[i]){
k -= a[i];
a[i] = 0;
}
else{
a[i] -= k;
k = 0;
}
ans += (a[i] * a[i]);
}
printf("%lld", ans);
return 0;
}
T3 czq的陌上花开
题目
思路
普普通通简单DP
\(dp[i] = min(dp[i - 1] + dp[i - 2]) + a[i]\)(dp[i]为经过i的最小值)
代码
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define int long long
using namespace std;
const int maxn = 1e5 + 5;
int a[maxn];
int n;
int dp[maxn];
signed main() {
scanf("%lld", &n);
for(int i = 1; i <= n; i ++){
scanf("%lld", &a[i]);
}
dp[1] = a[1];
dp[2] = a[1] + a[2];
for(int i = 3; i <= n; i ++){
dp[i] = max(dp[i - 1], dp[i - 2]) + a[i];
}
printf("%lld", dp[n]);
return 0;
}
T4 czq的骡马区间
题目
思路
用一个map
去存最后的那个那个点
吐槽
我谔谔,就是这道题我把题目理解错了,还能过样例就很神奇
代码
#include <map>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define int long long
using namespace std;
const int maxn = 1e5 + 5;
int a[maxn];
int sum[maxn];
map<int, int> mp;
int n;
int tail[maxn];
int ans;
signed main() {
scanf("%lld", &n);
for(int i = 1; i <= n; i ++){
scanf("%lld", &a[i]);
sum[i] = sum[i - 1] + a[i];
}
for(int i = n; i >= 1; i --){
tail[i] = mp[a[i]];
mp[a[i]] = i;
if(tail[i]){
ans += (sum[tail[i]] - sum[i - 1]);
}
}
printf("%lld", ans);
return 0;
}
T5 czq的原木种植
题目
思路
并查集板题
只是将自己的值用一个循环赋到父节点上,就可以用\(O(n)\) A
掉
代码
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define int long long
using namespace std;
const int maxn = 2e5 + 5;
int n, m;
int a[maxn];
int fa[maxn];
int father(int x){
if(fa[x] == x)return x;
return fa[x] = father(fa[x]);
}
void join(int x, int y){
int fax, fay;
fax = father(x);
fay = father(y);
if(fax != fay){
fa[fax] = fay;
}
}
int maxans = 0;
int minans = 0x3f3f3f3f;
bool vis[maxn];
int sum[maxn];
signed main() {
scanf("%lld %lld", &n, &m);
for(int i = 1; i <= n; i ++){
scanf("%lld", &a[i]);
fa[i] = i;
}
for(int i = 1; i <= m; i ++){
int x, y;
scanf("%lld %lld", &x, &y);
join(x, y);
}
for(int i = 1; i <= n; i ++){
if(father(i) != i)a[father(i)] += a[i];
}
for(int i = 1; i <= n; i ++){
int flag = father(i);
int tot = 0;
if(!vis[flag]){
tot = a[flag];
minans = min(minans, tot);
maxans = max(maxans, tot);
}
vis[flag] = 1;
}
printf("%lld %lld", maxans, minans);
}
结语
zyq一边爬楼梯,一边反省自己,
写了一篇反省的blog,结果连下周班刊征稿的文章都有了。。。。