B. Dreamoon Likes Permutations

题意 :

给一个长为n 的序列,然后要求分为两个长度大于1的序列,然后两个序列必须每个元素出现过一次,并且最大值等于序列的长度

思路

我自己用的特判,样例2wa到自闭,然后看大佬的, 大佬用set来存重复的数字, 当没有重复的数字的时候,判断两个set的大小和两个set 的最大值是否相等,若相等,代表成立则保存,

具体看代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6+6;
ll t, n;
ll a[maxn];

int main()
{
	cin >> t;
	while(t --)
	{
		cin >> n;
		map<ll ,ll> mp; // 用map来标记每个数字出现的次数
		set<ll> s1, s2; // s2是总的元素的集合
		for(int i = 1; i <= n; i ++)
		{
			cin >> a[i];
			mp[a[i]] ++;  
			s2.insert(a[i]);  //将每个元素放到s2中
		}
		
		vector<pair<ll,ll> > ve; // 这里是用来存答案的 
		for(int i = 1; i <= n; i ++)
		{
			if(mp[a[i]] == 2) 
			{ 
				s1.insert(a[i]); 
				mp[a[i]] --; 
				continue; 
			}
			
			if(s1.size()) // 如果当前s1 集合有元素
			{
				ll last_s1 = *s1.rbegin();
				ll last_s2 = *s2.rbegin();
				if(i-1 == last_s1 && last_s2 == (n-i+1) && s1.size()==last_s1 && s2.size()==last_s2)
					// 并且当前数字的前一个正好等于集合s1的最后一个值,集合s2的最后一个值也等于总的数减去s1集合的数量,并且他们的大小等于他们的最大的值 ,代表他们各出现过一次,那么当前一定符合条件
				{
					ve.push_back({last_s1,last_s2});
				}
			}
			
			if(mp[a[i]] == 1) // 如果是1的话,则换位置就可以两种情况都举到了
			{
				s1.insert(a[i]);
				s2.erase(a[i]);
			}
		}
		
		cout << ve.size() << endl;
		for(auto t : ve)
		{
			cout << t.first <<" " << t.second << endl;
		}
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值