b_51_前缀后缀集合(暴力前后缀哈希 / 双指针+双哈希)
求数组中前后缀可互相包含的集合对的数量
#include<bits/stdc++.h>
#define rep1(i,s,e) for(register int i=s;i<=e;i++)
#define rep2(i,e,s) for(register int i=e;i>=s;i--)
using namespace std;
typedef long long ll;
const int N=5e4+5;
ll n,ans,a[N];
bool chk1(unordered_set<int>& s1, unordered_set<int>& s2) {
for (int x : s2) if (s1.find(x)==s1.end()) return false;
return true;
}
bool chk2(unordered_set<int>& s1, unordered_set<int>& s2) {
for (int x : s1) if (s2.find(x)==s2.end()) return false;
return true;
}
int main() {
std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
cin>>n; rep1(i,1,n) cin>>a[i];
unordered_map<int, unordered_set<int>> m1,m2;
rep1(i,1,n) rep1(j,1,i) m1[i].insert(a[j]);
rep2(i,n,1) rep1(j,i,n) m2[i].insert(a[j]);
rep1(i,1,n)
rep1(j,1,n) {
auto& s1=m1[i], &s2=m2[j];
if (chk1(s1,s2) && chk2(s1,s2)) ans++;
}
cout<<ans;
return 0;
}
看了下最优解,其实不那么容易想到
#include<bits/stdc++.h>
#define rep1(i,s,e) for(register int i=s;i<=e;i++)
using namespace std;
typedef long long ll;
const int N=5e4+5;
ll n,ans,a[N],mp[N];
int main() {
std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
cin>>n; rep1(i,0,n-1) cin>>a[i];
unordered_set<int> ls, rs;
for (int l=0,r=n-1; l<n; l++) {
ls.insert(a[l]);
while (r>=0 && ls.find(a[r])!=ls.end()) { //ls包含右集合,
rs.insert(a[r--]);
mp[rs.size()]++;
}
ans+=mp[ls.size()]; //但累加时之类家ls中有的,因为rs可能很大,我只以ls为基准
}
cout<<ans;
return 0;
}