F2. Promising String (hard version)_BIT正序對+離散化+同餘分組
阿新 • • 發佈:2022-05-18
F2. Promising String (hard version)_BIT正序對+離散化+同餘分組
題目大意:
給一串由+-構成的序列,兩個-可以合併成一個+。一個串+-數量相等就稱其為好串,若一個串可以通過若干次合併變成好串那麼我們稱其為P串。現在給定一個串,問其中有多少的子串是P串。
思路和程式碼:
首先,一個子串的'-'的數量num0和'+'的數量num1之差為三的倍數即可(num0>=num1)。
考慮維護f陣列,fi表示[1,i]區間中num0和num1的差值。對於區間[l,r],只要滿足以下條件即可對答案產生貢獻
1)f[r]>=f[l-1]
2)(f[r] - f[l - 1]) % 3 == 0
對於條件2,我們變化一下式子可得:
(f[r] % 3 - f[l - 1] % 3) % 3 == 0
也就是說f[r] % 3要和 f[l - 1] % 3相等。於是我們可以對其模3,對同餘的進行分組。然後對012三種餘數維護一個“正序數”即可。
當然,f陣列會出現負數,但是BIT只能維護正數,所以我們可以對f陣列進行離散化。
int n , m , k ; void add(int x , int val , vct<ll> &tr){ while(x <= n + 2){ tr[x] += val ; x += (x & -x) ; } } ll query(int x , vct<ll> &tr){ ll res = 0 ; while(x){ res += tr[x] ; x -= (x & -x) ; } return res ; } int getid(int x , vct<ll> &d){ return lower_bound(all(d) , x) - d.begin() + 1 ; } void solve(){ string s ; cin >> n >> s ; vct<ll> f(n + 1 , 0) ; rep(i , 1 , n) f[i] = f[i - 1] + (s[i - 1] == '-' ? 1 : -1) ; vct<ll> d(1 , 0) ; rep(i , 1 , n) d.pb(f[i]) ; sort(all(d)) ; d.erase(unique(all(d)) , d.end()) ; vct<vct<ll> > tr(3 , vct<ll> (n + 2 , 0)) ; ll ans = 0 ; rep(i , 0 , n){ int p = getid(f[i] , d) ; ans += query(p , tr[p % 3]) ; add(p , 1 , tr[p % 3]) ; } cout << ans << "\n" ; }//code_by_tyrii
小結: