2020牛客暑期多校訓練營(第二場)Greater and Greater
阿新 • • 發佈:2020-07-20
題目連結
https://ac.nowcoder.com/acm/contest/5667/G
題目大意
給你一個長度為 N 的陣列 A 和一個長度為 M 的陣列 B
問 A 中存在多少個長度為 M 的子串使得 Ai >= B1 , Ai+1 >= B2 , ... , Ai+m >= Bm
解題思路
樣例為N = 6 , M = 3 , A = { 1,4,2,8,5,7} , B = {2,3,3}
我們對每個 Bj 求一個長度為 N 的 bitset ,設為Bis [ j ]
其意義為 若 Ai 大於等於 Bj , 則 Bis[ pos[ Ai ] ] = 1 , 否則為 0
那麼對應樣例我們得到的 Bis 分別為
容易發現若存在這麼一條右斜線 , 可以從 1 走到 m , 則 ans ++
我們將第 J 個 Bis[j] 左移 J - 1位 , 得到
於是原來的斜線就變成了豎線
那麼我們只要把所有的 Bis[j] 左移之後進行 & 運算 , 然後統計最後的結果有多少 1 即可
那麼 Bis [j] 怎麼求呢?
我們可以先對 A , B 進行降序排序 , 然後執行下圖操作(畫的有點醜hh)
AC_Code
#include<bits/stdc++.h> #define fi first #define se second using namespace std; const intN = 2e5 + 10; pair<int , int>a[N] , b[N]; bitset<N>ans , now; signed main() { ios::sync_with_stdio(false) , cin.tie(0) , cout.tie(0); int n , m ; cin >> n >> m ; for(int i = 1 ; i <= n ; i ++) cin >> a[i].fi , a[i].se = i; for(int i = 1 ; i <= m ; i ++) cin >> b[i].fi , b[i].se = i; sort(a+ 1 , a + 1 + n , greater<pair<int , int>>()); sort(b + 1 , b + 1 + m , greater<pair<int , int>>()); ans.set() , now.reset(); int pos = 1; for(int i = 1 ; i <= m ; i ++) { while(pos <= n && a[pos].fi >= b[i].fi) now.set(a[pos].se) , pos ++ ; ans &= now >> b[i].se; } cout << ans.count() << '\n'; return 0; }