题目大意翻译:
样例输入输出:
4
1
1
3
2 2 3
4
2 1 1 2
4
4 4 4 4
1
13
9
40
题目理解:
从样例出发,根据题目讲述的过程模拟一次样例的过程为如下所示
(以第二组,第三组数据为例)
没错,或许你已经发现了,只要每一次加上数组的每个值之后再算出下一个MAD(a[i]),就可以接着加下一个数组了,然后循环直到这个数组中数组全为0,那么先上代码:
#include<bits/stdc++.h>
using namespace std;
set <int> a;
vector <int> b,c;
int main()
{
long long int t,n,vab,num,shu;
cin>>t;
while(t--){
num = 0;
cin>>n;
b.clear();
for(int i=0;i<n;i++){
cin>>vab;
b.push_back(vab);
num += vab;
}
while(b.size() > 0){
shu = 0;
c.clear();
a.clear();
for(int i=0;i<b.size();i++){
if(a.count(b[i]) == 1 && b[i] > shu)
shu = b[i];
else
a.insert(b[i]);
if(shu != 0){
c.push_back(shu);
num += shu;
}
}
b = c;
}
cout<<num<<endl;
}
return 0;
}
这里我使用了vector数组,并且每一次更新这个数组的值。
如果你上交了这个代码,那么你会获得一个TLE,在第四个样例会出现超时的情况,因为这一题的n最大能取到,如果暴力搜索会导致直接超时。
那么你就要寻找这个规律了,并且减少他的循环次数。
但是题目中给的样例不足以能寻找这个规律,那么给出以下样例。
想必你能看出这是有规律的,在第二次循环的时候,数组已经是按照从小到大排序的了,而在第三次循环的时候,数组不仅按照从小到大排序,甚至重复的个数都是偶数个(除了最后一个数)。那么从第三次循环之后,可以记录每个数组总和,然后每次循环之后踢掉最后一个数,然后直到这个数组中没有数,我使用了栈(stack)来完成这个过程,那么直接上代码:
#include<bits/stdc++.h>
using namespace std;
set <int> a;
vector <int> b,d;
stack <int> c;
long long int t,n,vab,num,shu,xiaonum;
int main()
{
cin>>t;
while(t--){
xiaonum = 0; num = 0; shu = 0;
a.clear(); b.clear(); d.clear();
while(!c.empty()) c.pop();
cin>>n;
for(int i=0;i<n;i++){
cin>>vab;
b.push_back(vab);
num += vab;
}
for(int i=0;i<b.size();i++){
if(a.count(b[i]) == 1 && b[i] > shu) shu = b[i];
else a.insert(b[i]);
if(shu != 0){
d.push_back(shu);
num += shu;
}
}
if(d.size() > 0){
shu = 0;
for(int i=1;i<d.size();i++){
if(d[i] == d[i-1]) shu = d[i];
if(shu != 0) c.push(shu);
num += shu;
xiaonum += shu;
}
}
while(c.size() > 0){
xiaonum -= c.top();
c.pop();
num += xiaonum;
}
cout<<num<<endl;
}
return 0;
}
这里使用了集合a来存储是否有重复的数,用数组b,d来存储2次循环的结果,用栈c来存储第三次循环后的结果,用xiaonum来存储每个数组的总和,因为第三次循环之后,每次只踢出一个尾巴值,所以每次只要让xiaonum去减去c.top()就可以了,然后让num去加上的xiaonum
最后的温馨提示:此题需要开long long
总的来说是一道很有意思的题目,以上是我的题解。