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<bits/stdc++.h>
using namespace std;
#define int long long
#define endl "\n"
const int N=5e5+10;
int a[N];
void solve(){int n;cin>>n;set<int>s;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<<ans<<endl;
}
signed main(){ios::sync_with_stdio(false);cin.tie(nullptr);int q=1;cin>>q;while(q--) solve();return 0;
}