寒假Day28:[蓝桥杯2019初赛]后缀表达式+修改数组

 [蓝桥杯2019初赛]后缀表达式

题目链接:http://oj.ecustacm.cn/problem.php?id=1467

题目描述

给定N 个加号、M 个减号以及N + M + 1 个整数A1,A2,...,AN+M+1
小明想知道在所有由这N 个加号、M 个减号以及N + M +1 个整数凑出的合法的后缀表达式中,结果最大的是哪一个?
请你输出这个最大的结果。
例如使用1 2 3 + -,则“2 3 + 1 -” 这个后缀表达式结果是4,是最大的。

输入

第一行包含两个整数N 和M。
第二行包含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 }
View Code

补充:

  • 前缀表达式求值

例如前缀表达式“- × + 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 }
View Code

[蓝桥杯2019初赛]修改数组

给定一个长度为N 的数组A = [A1, A2,...,AN],数组中有可能有重复出现的整数。
现在小明要按以下方法将其修改为没有重复整数的数组。小明会依次修改A2,A3,..., AN。
当修改Ai 时,小明会检查Ai 是否在A1~ Ai-1 中出现过。
如果出现过,则小明会给Ai 加上1 ;
如果新的Ai 仍在之前出现过,小明会持续给Ai 加1 ,直到Ai 没有在A1~Ai-1中出现过。
当AN 也经过上述修改之后,显然A数组中就没有重复的整数了。
现在给定初始的A 数组,请你计算出最终的A 数组。

输入

第一行包含一个整数N(1<=N<=100000)
第二行包含N个整数A1,A2,...,AN(1<=Ai<=1000000)

输出

输出N个整数,依次是最终的A1,A2,...,AN

样例输入 

5
2 1 1 3 4

样例输出 

2 1 3 4 5

思路:一开始的想法,我用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 }
View Code

待解决:

  • 蓝桥杯后缀表达式,原因写在上面题目之后了
原文地址:https://www.cnblogs.com/OFSHK/p/12309309.html