- 伍衍 的博客
DAY1
- @ 2024-7-8 20:47:56
T1: 1.没有AC的原因:在做题时想得太多了,所以到后面越想越复杂,最后导致想不全。改正方法:在做题时不要想太复杂,实在不行就换一种思路。
2.题解: 暴力题:考虑所有的情况:1234567->A5B,121314151617->11A,随后求出最小值即可。 代码:
#include <bits/stdc++.h>
using namespace std;
int main(){
freopen("gem.in", "r", stdin);
freopen("gem.out", "w", stdout);
long long a,b;
cin >> a >> b;
cout << min(11*a,a+5*b);
}
T2: 这一题看着复杂,其实只是让我们找一个最长不为升序子序列的长度。分类讨论: 1.数组为升序:此时不论怎么取都不行,所以只能输出0; 2.数组不为升序:此时数组本身就满足要求,输出数组长度; 此题为AC。 代码:
#include <bits/stdc++.h>
typedef long long inf;
using namespace std;
const inf N=2e5+10;
inf a[N],b[N];
int main(){
freopen("hsz.in","r",stdin);
freopen("hsz.out","w",stdout);
inf n;
cin >> n;
for(inf i=1;i<=n;i++){
cin >> a[i];
b[i]=a[i];
}
sort(a+1,a+n+1);
for(inf i=1;i<=n;i++){
if(a[i]!=b[i]){
cout << n;
return 0;
}
}
cout << 0;
return 0;
}
``
T3: 1.未AC原因:错误的用最大值和最小值计算,其实题目与这两个无关。改正方法:多思考,不要只想一会就开始写。 2:题解: (1).此题与极端值无关,每一个数都有可能成为极小值,所以要循环遍历每个数。 (2).使用前后缀和,求出每个数左右两边数字之和; (3).此时问题简化为n=3,求出max(abs(a[i]-左边和),abs(a[i]-右边和)); 代码:
#include <bits/stdc++.h>
typedef long long inf;
using namespace std;
const inf N=2e5+50;
inf a[N],b[N],c[N];
int main(){
freopen("num.in","r",stdin);
freopen("num.out","w",stdout);
inf n;
cin >> n;
for(inf i=1;i<=n;i++){
cin >> a[i];
b[i]=b[i-1]+a[i];
}
for(inf i=n;i>=1;i--){
c[i]=c[i+1]+a[i];
}
inf mx=-1;
for(inf i=n;i>=1;i--){
c[i]=c[i+1]+a[i];
mx=max(mx,max(c[i+1]-a[i],b[i-1]-a[i]));
}
cout << mx;
}
题目传送门 .未的原因:在其他提上花了过多的时间,导致没有时间做这道题目。解决方法:提高做题效率,争取把题做完。 .题解: 建一个哈希栈,用来储存答案。 如果遇到,则往哈希栈中新建一个哈希表。 如果遇到,说明算完了这一层。此时看括号右边有没有数字,有则取出,没有则视为。随后此哈希表,并且用括号内原子的数量乘弹出的数字得到结果,加到上一层。 如果不为括号,就通过字符串将原子名称取出。若后面有数字则取出,否则视为1。随后加入到哈希表。 输出哈希表. .易错点: 由于本题需要按字典序排序所以我们不使用_(无序哈希表),而是使用(有序哈希表)。 .代码
#include<bits/stdc++.h>
using namespace std;
stack<map<string, int>> stk;
string s;
int i,len;
int get_num(){
if (i==len||!isdigit((s[i]))) return 1;
int num=0;
while (isdigit(s[i])&&i<len){
num=num*10+s[i]-'0';
i++;
}
return num;
}
string get_atom(){
string atom;
atom+=s[i++];
while(i<len&&s[i]>='a'&&s[i]<='z')
atom+=s[i++];
return atom;
}
int main(){
freopen("atom.in","r",stdin);
freopen("atom.out","w",stdout);
cin >> s;
len=s.size();
stk.push({});
while (i<len){
char ch=s[i];
if(ch=='('){
i++;
stk.push({});
}
else if(ch==')'){
i++;
int num=get_num();
auto atom_num=stk.top();
stk.pop();
for(auto &it:atom_num){
string k=it.first;
int v=it.second;
stk.top()[k]+=v*num;
}
}
else{
string atom=get_atom();
int num=get_num();
stk.top()[atom]+=num;
}
}
auto atn=stk.top();
for(auto&it:atn){
string k=it.first;
int v=it.second;
cout << k << " " << v << endl;
}
return 0;
}
T5: 1.未AC原因:对DFS的熟练度不高,导致只能写出一部分。改正方法:课后多复习DFS,争取弄懂它; 2.DFS题解: (1)定义两个方向数组,控制上下左右; (2)越界不处理,高度太高不处理,其他情况下都需要递归下一层。 (3)用f数组保存当前状态,如果不等于0(走过了),就return f[x][y]; (4)最后一步,所有的递归后面都要+1; 代码:
#include <bits/stdc++.h>
using namespace std;
const int N=150;
int a[N][N],f[N][N];
int n,m,ans;
int ansi,ansj;
int _x[]={1,0,-1,0};
int _y[]={0,1,0,-1};
int dfs(int x,int y){
if(f[x][y]) return f[x][y];
for(int i=0;i<4;i++){
int dx=x+_x[i],dy=y+_y[i];
if(dx>n||dy>m||dx<1||dy<1) continue;
if(a[x][y]<=a[dx][dy]) continue;
f[x][y]=max(f[x][y],dfs(dx,dy)+1);
}
return f[x][y];
}
int main(){
freopen("treasure.in","r",stdin);
freopen("treasure.out","w",stdout);
cin >> n >> m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin >> a[i][j];
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
if(dfs(i,j)+1>ans){
ans=dfs(i,j)+1;
ansi=i;
ansj=j;
}
}
cout << ansi << " " << ansj << "\n";
cout << ans;
return 0;
}
T6 1.未AC原因:前面题用时太久,导致没有时间。改正方法:加快做题速度,实在想不出就换一道题。 2.DP题解: (1)状态表示:集合:将后i朵花高度变为0的所有方案。属性:Min; (2)状态计算:如果f[i]>f[i+1],则没有影响,不用计算;如果f[i]<=f[i+1],则前面的花会耽误时间,总时间为f[i+1]+1; (3)输出:f[1]; 代码:
#include <bits/stdc++.h>
typedef long long ll;
const ll N=1e5+50;
ll f[N];
using namespace std;
int main(){
freopen("flowers.in","r",stdin);
freopen("flowers.out","w",stdout);
ll n;
cin >> n;
for(ll i=1;i<=n;i++){
cin >> f[i];
}for(ll i=n-1;i>=1;i--){
if(f[i]<=f[i+1]) f[i]=f[i+1]+1;
}
cout << f[1];
}