b_51_字首字尾集合(暴力前後綴雜湊 / 雙指標+雙雜湊)
阿新 • • 發佈:2020-10-25
求陣列中前後綴可互相包含的集合對的數量
#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; }