codeforces C. Cool Partition

目录

题目简述:

思路:

总代码:



https://codeforces.com/contest/2117/problem/C

 

题目简述:

给定一个整数数组,现要求你对数组进行分割,但需满足条件:前一个子数组中的值必须在后一个子数组中全部出现(例如 123142,可以分成12 和3142这俩子数组)求子数组个数

思路:

关键思路很好想:尽可能早的进行数组分割

具体实操很难搞

我们可以维护一个集合,遍历整个数组,不断弹出当前所遍历到的值,如果这个集合为空了,那么此时就满足的分割条件,且是最优分割位置,此时ans++,此时集合需要更新成前一个集合(假设有集合a1,a2,a3,此时满足了a1中全部元素在a2中全出现了,下次再判断时就要满足a2中全部元素在a3中全部出现,所以把集合更新成a2)

接下来我们想用什么容器存呢?

这个容器得可以实现:任意删除,判空,去重(若a1中出现俩相同元素如a1=112,a2中只需出现一次1即可,所以要去重)。

那很显然了就是set。

总结:

使用集合s记录当前段的所有元素

从左到右遍历数组,对于每个元素a[i],将其从集合中删除

当集合为空时,说明当前段的所有元素都能在后续段中找到(因为已被删除),可以在此处分割

分割后重置集合,记录新段的起始位置

最后处理可能未完成的段

总代码:

#include
using namespace std;
#define int long long
#define endl "\n"
const int N=5e5+10;
int a[N];
void solve(){
    int n;
    cin>>n;
    sets;
    for(int i=1;i<=n;i++)cin>>a[i];
    int ans=1;int r=1;
    for(int i=1;i<=n;i++) {
        s.erase(a[i]);
        if(s.empty()){
            ans++;
            for(int j=r;j<=i;j++)s.insert(a[j]);
            r=i+1;
        }
    }
    if(!s.empty())ans--;
    cout<>q;
    while(q--) solve();
    return 0;
}

你可能感兴趣的:(枚举,STL大法,贪心,c语言,数据结构,算法)