[蓝桥杯2019初赛]后缀表达式
题目链接:http://oj.ecustacm.cn/problem.php?id=1467
题目描述
小明想知道在所有由这N 个加号、M 个减号以及N + M +1 个整数凑出的合法的后缀表达式中,结果最大的是哪一个?
请你输出这个最大的结果。
例如使用1 2 3 + -,则“2 3 + 1 -” 这个后缀表达式结果是4,是最大的。
输入
第二行包含N + M + 1 个整数A1,A2,...,AN+M+1
0<=N,M<=100000,-10^9<=Ai<=10^9
输出
样例输入 Copy
1 1
1 2 3
样例输出 Copy
4
https://blog.csdn.net/ryo_218/article/details/89515960
https://blog.csdn.net/weixin_42765557/article/details/88914230
思路可以看一下上面两个博客,这俩博客的代码也存在问题,
由于我的代码没过完所有数据,暂不放思路。
网上的代码貌似都不对,无法过完全部数据,
我的代码(没有AC,待解决):
1 #include<stdio.h> 2 #include<iostream> 3 #include<algorithm> 4 #include<map> 5 using namespace std; 6 const int N=100020; 7 typedef long long ll; 8 9 ll a[N],z[N],f[N]; 10 11 bool cmp1(ll x,ll y) 12 { 13 return x>y; 14 } 15 16 int main() 17 { 18 ll n,m,sum=0,sum1=0,sum2=0; 19 cin>>n>>m; 20 int p=0,q=0; 21 for(int i=0; i<n+m+1; i++) 22 { 23 cin>>a[i]; 24 sum+=a[i]; 25 if(a[i]>=0) 26 z[p++]=a[i],sum1+=a[i]; 27 else 28 f[q++]=a[i],sum2+=a[i]; 29 } 30 // if(n==0) 31 // cout<<(-1)*sum<<endl; 32 if(m==0) 33 cout<<sum<<endl; 34 else 35 { 36 sum=0; 37 sort(z,z+p); 38 sort(f,f+q); 39 if(m==q) 40 sum=sum1+(-1)*sum2; 41 else if(m<q)//负数比负号多 42 { 43 sum=0; 44 ll ss=0; 45 int s=1; 46 for(int i=0;i<q;i++) 47 { 48 if(s<m) 49 sum=sum+(-1)*f[i],s++; 50 else 51 ss+=f[i]; 52 } 53 sum=sum+(-1)*ss+sum1; 54 // int s=0; 55 // for(int i=0;i<q;i++) 56 // { 57 // if(s<m) 58 // sum-=f[i],s++; 59 // else 60 // sum+=f[i]; 61 // } 62 // sum+=sum1; 63 } 64 else if(m>q)//负号比负数多 65 { 66 int s=m-q; 67 for(int i=0; i<p; i++) 68 { 69 if(s) 70 sum=sum-z[i],s--; 71 else 72 sum+=z[i]; 73 } 74 sum+=sum2*(-1); 75 } 76 cout<<sum<<endl; 77 } 78 return 0; 79 }
补充:
- 前缀表达式求值
例如前缀表达式“- × + 3 4 5 6”计算的步骤如下:
(1) 从右至左扫描,将6、5、4、3压入堆栈;
(2) 遇到+运算符,因此弹出3和4(3为栈顶元素,4为次顶元素,注意与后缀表达式做比较),计算出3+4的值,得7,再将7入栈;
(3) 接下来是×运算符,因此弹出7和5,计算出7×5=35,将35入栈;
(4) 最后是-运算符,计算出35-6的值,即29,由此得出最终结果。
- 后缀表达式:又称逆波兰式,指的是不包含括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行(不再考虑运算符的优先规则)。
后缀表达式计算:
例如:后缀表达式为“2 3 + 4 × 5 -”计算过程如下:
(1)从左至右扫描,将 2 和 3 压入堆栈;
(2)遇到 + 运算符,因此弹出 3 和 2( 3 为栈顶元素,2 为次顶元素,注意与前缀表达式做比较),计算出 3+2 的值,得 5,再将 5 入栈;
(3)将 4 入栈;
(4)接下来是 × 运算符,因此弹出 4 和 5,计算出 4 × 5 = 20,将 20 入栈;
(5)将 5 入栈;
(6)最后是-运算符,计算出 20-5 的值,即 15,由此得出最终结果。
- 中缀表达式的话就是一般我们看到的那种正常表达式啦
[蓝桥杯2019初赛]不同子串
题意:判断原串中有多少不同字串
思路:暴力+set即可
AC代码:
1 #include<stdio.h> 2 #include<iostream> 3 #include<algorithm> 4 #include<map> 5 #include<set> 6 using namespace std; 7 const int N=100020; 8 typedef long long ll; 9 10 set<string>s; 11 12 int main() 13 { 14 string ss,a; 15 a="0100110001010001"; 16 for(int i=0;i<a.length();i++) 17 { 18 ss.clear(); 19 ss+=a[i]; 20 s.insert(ss); 21 for(int j=i+1;j<a.length();j++) 22 { 23 ss+=a[j]; 24 s.insert(ss); 25 } 26 } 27 cout<<s.size()<<endl; 28 return 0; 29 }
[蓝桥杯2019初赛]修改数组
现在小明要按以下方法将其修改为没有重复整数的数组。小明会依次修改A2,A3,..., AN。
当修改Ai 时,小明会检查Ai 是否在A1~ Ai-1 中出现过。
如果出现过,则小明会给Ai 加上1 ;
如果新的Ai 仍在之前出现过,小明会持续给Ai 加1 ,直到Ai 没有在A1~Ai-1中出现过。
当AN 也经过上述修改之后,显然A数组中就没有重复的整数了。
现在给定初始的A 数组,请你计算出最终的A 数组。
输入
第二行包含N个整数A1,A2,...,AN(1<=Ai<=1000000)
输出
思路:一开始的想法,我用book把之前没有出现过的标记,出现过的while进行暴力,但会造成超时,拿不到全部的分数,貌似80%,感觉也没有什么新奇的思路,于是查了一下,有新奇的思路->并查集
参考博客:https://blog.csdn.net/weixin_42765557/article/details/89480557
如何引入和判断并查集关键:
for(int i=0; i<n; i++) { cin>>a[i]; int x=getf(a[i]); a[i]=x; f[x]=getf(x+1); }
AC代码:
1 #include<stdio.h> 2 #include<iostream> 3 #include<algorithm> 4 using namespace std; 5 const int N=100020; 6 typedef long long ll; 7 8 int a[N],f[N]; 9 10 int getf(int x) 11 { 12 if(x==f[x]) 13 return x; 14 return f[x]=getf(f[x]); 15 } 16 17 int main() 18 { 19 for(int i=1; i<=N; i++) 20 f[i]=i; 21 int n; 22 cin>>n; 23 for(int i=0; i<n; i++) 24 { 25 cin>>a[i]; 26 int x=getf(a[i]); 27 a[i]=x; 28 f[x]=getf(x+1); 29 } 30 for(int i=0; i<n-1; i++) 31 cout<<a[i]<<" "; 32 cout<<a[n-1]<<endl; 33 return 0; 34 }
待解决:
- 蓝桥杯后缀表达式,原因写在上面题目之后了