Codeforces Round 960 (Div. 2) Problem C

原题链接:Problem - C - Codeforces

题目大意翻译:

样例输入输出:

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最大能取到2*10^{5},如果暴力搜索会导致n^{2}直接超时。

那么你就要寻找这个规律了,并且减少他的循环次数。

但是题目中给的样例不足以能寻找这个规律,那么给出以下样例。

想必你能看出这是有规律的,在第二次循环的时候,数组已经是按照从小到大排序的了,而在第三次循环的时候,数组不仅按照从小到大排序,甚至重复的个数都是偶数个(除了最后一个数)。那么从第三次循环之后,可以记录每个数组总和,然后每次循环之后踢掉最后一个数,然后直到这个数组中没有数,我使用了栈(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

总的来说是一道很有意思的题目,以上是我的题解。

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值