题意 :
给一个长为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;
}